diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-12-16 05:34:03 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1997-12-16 05:34:03 +0000 |
commit | 967c65a99059fd459b956c1588ce0ba227912c4e (patch) | |
tree | 8224d013ff5d255420713d05610c7efebd204d2a /arch/i386 | |
parent | e20c1cc1656a66a2773bca4591a895cbc12696ff (diff) |
Merge with Linux 2.1.72, part 1.
Diffstat (limited to 'arch/i386')
-rw-r--r-- | arch/i386/boot/compressed/head.S | 10 | ||||
-rw-r--r-- | arch/i386/boot/compressed/misc.c | 2 | ||||
-rw-r--r-- | arch/i386/boot/setup.S | 4 | ||||
-rw-r--r-- | arch/i386/config.in | 13 | ||||
-rw-r--r-- | arch/i386/defconfig | 23 | ||||
-rw-r--r-- | arch/i386/kernel/bios32.c | 6 | ||||
-rw-r--r-- | arch/i386/kernel/entry.S | 37 | ||||
-rw-r--r-- | arch/i386/kernel/head.S | 14 | ||||
-rw-r--r-- | arch/i386/kernel/init_task.c | 1 | ||||
-rw-r--r-- | arch/i386/kernel/irq.h | 2 | ||||
-rw-r--r-- | arch/i386/kernel/process.c | 25 | ||||
-rw-r--r-- | arch/i386/kernel/ptrace.c | 12 | ||||
-rw-r--r-- | arch/i386/kernel/signal.c | 654 | ||||
-rw-r--r-- | arch/i386/kernel/sys_i386.c | 21 | ||||
-rw-r--r-- | arch/i386/kernel/trampoline.S | 2 | ||||
-rw-r--r-- | arch/i386/kernel/traps.c | 4 | ||||
-rw-r--r-- | arch/i386/kernel/vm86.c | 9 | ||||
-rw-r--r-- | arch/i386/lib/delay.c | 2 | ||||
-rw-r--r-- | arch/i386/math-emu/errors.c | 4 | ||||
-rw-r--r-- | arch/i386/math-emu/fpu_entry.c | 4 |
20 files changed, 572 insertions, 277 deletions
diff --git a/arch/i386/boot/compressed/head.S b/arch/i386/boot/compressed/head.S index 6f68a92d4..30384a3a3 100644 --- a/arch/i386/boot/compressed/head.S +++ b/arch/i386/boot/compressed/head.S @@ -37,7 +37,7 @@ startup_32: cld cli - movl $(KERNEL_DS),%eax + movl $(__KERNEL_DS),%eax mov %ax,%ds mov %ax,%es mov %ax,%fs @@ -56,7 +56,7 @@ startup_32: movl %eax,%esp pushl 0 # Clear NT popfl - ljmp $(KERNEL_CS), $0x100000 # Into C and sanity + ljmp $(__KERNEL_CS), $0x100000 # Into C and sanity 2: #endif @@ -92,7 +92,7 @@ startup_32: orl %eax,%eax jnz 3f xorl %ebx,%ebx - ljmp $(KERNEL_CS), $0x100000 + ljmp $(__KERNEL_CS), $0x100000 /* * We come here, if we were loaded high. @@ -116,7 +116,7 @@ startup_32: popl %eax # hcount movl $0x100000,%edi cli # make sure we don't get interrupted - ljmp $(KERNEL_CS), $0x1000 # and jump to the move routine + ljmp $(__KERNEL_CS), $0x1000 # and jump to the move routine /* * Routine (template) for moving the decompressed kernel in place, @@ -136,5 +136,5 @@ move_routine_start: * so we set esp here. */ mov $0x90000,%esp - ljmp $(KERNEL_CS), $0x100000 + ljmp $(__KERNEL_CS), $0x100000 move_routine_end: diff --git a/arch/i386/boot/compressed/misc.c b/arch/i386/boot/compressed/misc.c index 9a556baf4..e4a6ede9a 100644 --- a/arch/i386/boot/compressed/misc.c +++ b/arch/i386/boot/compressed/misc.c @@ -285,7 +285,7 @@ long user_stack [STACK_SIZE]; struct { long * a; short b; - } stack_start = { & user_stack [STACK_SIZE] , KERNEL_DS }; + } stack_start = { & user_stack [STACK_SIZE] , __KERNEL_DS }; void setup_normal_output_buffer() { diff --git a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S index edc0fe0ff..11310bd49 100644 --- a/arch/i386/boot/setup.S +++ b/arch/i386/boot/setup.S @@ -594,7 +594,7 @@ flush_instr: xor bx,bx ! Flag to indicate a boot ! NOTE: For high loaded big kernels we need a -! jmpi 0x100000,KERNEL_CS +! jmpi 0x100000,__KERNEL_CS ! ! but we yet haven't reloaded the CS register, so the default size ! of the target offset still is 16 bit. @@ -603,7 +603,7 @@ flush_instr: ! Manual, Mixing 16-bit and 32-bit code, page 16-6) db 0x66,0xea ! prefix + jmpi-opcode code32: dd 0x1000 ! will be set to 0x100000 for big kernels - dw KERNEL_CS + dw __KERNEL_CS kernel_version: .ascii UTS_RELEASE diff --git a/arch/i386/config.in b/arch/i386/config.in index f7042fa33..7595ab5fe 100644 --- a/arch/i386/config.in +++ b/arch/i386/config.in @@ -84,6 +84,8 @@ if [ "$CONFIG_NET" = "y" ]; then endmenu fi +source drivers/net/hamradio/Config.in + mainmenu_option next_comment comment 'ISDN subsystem' @@ -102,6 +104,17 @@ if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then fi endmenu +# Conditionally compile in the Uniform CD-ROM driver +if [ "$CONFIG_BLK_DEV_IDECD" = "y" -o "$CONFIG_BLK_DEV_SR" = "y" -o "$CONFIG_SBPCD" = "y" -o "$CONFIG_MCD" = "y" -o "$CONFIG_CM206" = "y" -o "$CONFIG_CDU31A" = "y" ]; then + define_bool CONFIG_CDROM y +else + if [ "$CONFIG_BLK_DEV_IDECD" = "m" -o "$CONFIG_BLK_DEV_SR" = "m" -o "$CONFIG_SBPCD" = "m" -o "$CONFIG_MCD" = "m" -o "$CONFIG_CM206" = "m" -o "$CONFIG_CDU31A" = "m" ]; then + define_bool CONFIG_CDROM m + else + define_bool CONFIG_CDROM n + fi +fi + source fs/Config.in source fs/nls/Config.in diff --git a/arch/i386/defconfig b/arch/i386/defconfig index bd100e08d..222b10939 100644 --- a/arch/i386/defconfig +++ b/arch/i386/defconfig @@ -58,7 +58,7 @@ CONFIG_BLK_DEV_IDECD=y CONFIG_BLK_DEV_CMD640=y # CONFIG_BLK_DEV_CMD640_ENHANCED is not set CONFIG_BLK_DEV_RZ1000=y -CONFIG_BLK_DEV_TRITON=y +CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDE_CHIPSETS is not set # @@ -74,22 +74,27 @@ CONFIG_BLK_DEV_TRITON=y # # Networking options # +CONFIG_PACKET=y # CONFIG_NETLINK is not set # CONFIG_FIREWALL is not set # CONFIG_NET_ALIAS 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_ACCT is not set +# CONFIG_IP_MASQUERADE 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_PCTCP is not set # CONFIG_INET_RARP is not set -CONFIG_PATH_MTU_DISCOVERY=y CONFIG_IP_NOSR=y CONFIG_SKB_LARGE=y @@ -98,7 +103,6 @@ CONFIG_SKB_LARGE=y # # CONFIG_IPX is not set # CONFIG_ATALK is not set -# CONFIG_AX25 is not set # # SCSI support @@ -179,14 +183,20 @@ CONFIG_EEXPRESS_PRO100=y # CONFIG_FDDI is not set # CONFIG_DLCI is not set # CONFIG_PPP is not set -# CONFIG_NET_RADIO is not set # CONFIG_SLIP is not set +# CONFIG_STRIP is not set +# CONFIG_WAVELAN is not set # CONFIG_TR is not set # CONFIG_WAN_DRIVERS is not set # CONFIG_LAPBETHER is not set # CONFIG_X25_ASY is not set # +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# # ISDN subsystem # # CONFIG_ISDN is not set @@ -195,6 +205,7 @@ CONFIG_EEXPRESS_PRO100=y # CD-ROM drivers (not for SCSI or IDE/ATAPI drives) # # CONFIG_CD_NO_IDESCSI is not set +CONFIG_CDROM=y # # Filesystems @@ -214,6 +225,7 @@ CONFIG_NFS_FS=y CONFIG_NFSD=y CONFIG_SUNRPC=y CONFIG_LOCKD=y +# CONFIG_CODA_FS is not set # CONFIG_SMB_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_SYSV_FS is not set @@ -234,6 +246,7 @@ CONFIG_AUTOFS_FS=y 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_MOUSE=y diff --git a/arch/i386/kernel/bios32.c b/arch/i386/kernel/bios32.c index e98819258..8e41188c3 100644 --- a/arch/i386/kernel/bios32.c +++ b/arch/i386/kernel/bios32.c @@ -1,7 +1,7 @@ /* * bios32.c - BIOS32, PCI BIOS functions. * - * $Id: bios32.c,v 1.14 1997/08/02 22:20:57 mj Exp $ + * $Id: bios32.c,v 1.5 1997/12/02 01:48:00 ralf Exp $ * * Sponsored by * iX Multiuser Multitasking Magazine @@ -528,7 +528,7 @@ static unsigned long bios32_entry = 0; static struct { unsigned long address; unsigned short segment; -} bios32_indirect = { 0, KERNEL_CS }; +} bios32_indirect = { 0, __KERNEL_CS }; /* * Returns the entry point for the given service, NULL on error @@ -570,7 +570,7 @@ static long pcibios_entry = 0; static struct { unsigned long address; unsigned short segment; -} pci_indirect = { 0, KERNEL_CS }; +} pci_indirect = { 0, __KERNEL_CS }; __initfunc(static int check_pcibios(void)) { diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index dffc13795..cf99d6e2e 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S @@ -73,15 +73,15 @@ VM_MASK = 0x00020000 state = 0 counter = 4 priority = 8 -signal = 12 -blocked = 16 -flags = 20 -dbgreg6 = 52 -dbgreg7 = 56 -exec_domain = 60 +flags = 12 +sigpending = 16 +dbgreg6 = 44 +dbgreg7 = 48 +exec_domain = 52 ENOSYS = 38 + #define SAVE_ALL \ cld; \ push %es; \ @@ -93,7 +93,7 @@ ENOSYS = 38 pushl %edx; \ pushl %ecx; \ pushl %ebx; \ - movl $(KERNEL_DS),%edx; \ + movl $(__KERNEL_DS),%edx; \ mov %dx,%ds; \ mov %dx,%es; @@ -170,10 +170,7 @@ ret_from_sys_call: ret_with_reschedule: cmpl $0,SYMBOL_NAME(need_resched) jne reschedule - movl blocked(%ebx),%eax - movl %eax,%esi # save blocked in %esi for signal handling - notl %eax - andl signal(%ebx),%eax + cmpl $0,sigpending(%ebx) jne signal_return RESTORE_ALL ALIGN @@ -181,7 +178,7 @@ signal_return: testl $(VM_MASK),EFLAGS(%esp) pushl %esp jne v86_signal_return - pushl %esi + pushl $0 call SYMBOL_NAME(do_signal) addl $8,%esp RESTORE_ALL @@ -190,7 +187,7 @@ v86_signal_return: call SYMBOL_NAME(save_v86_state) movl %eax,%esp pushl %eax - pushl %esi + pushl $0 call SYMBOL_NAME(do_signal) addl $8,%esp RESTORE_ALL @@ -255,7 +252,7 @@ error_code: xchgl %ecx, ES(%esp) # get the address and save es. pushl %eax # push the error code pushl %edx - movl $(KERNEL_DS),%edx + movl $(__KERNEL_DS),%edx mov %dx,%ds mov %dx,%es GET_CURRENT(%ebx) @@ -529,6 +526,16 @@ ENTRY(sys_call_table) .long SYMBOL_NAME(sys_setresgid) /* 170 */ .long SYMBOL_NAME(sys_getresgid) .long SYMBOL_NAME(sys_prctl) - .rept NR_syscalls-172 + .long SYMBOL_NAME(sys_rt_sigreturn) + .long SYMBOL_NAME(sys_rt_sigaction) + .long SYMBOL_NAME(sys_rt_sigprocmask) /* 175 */ + .long SYMBOL_NAME(sys_rt_sigpending) + .long SYMBOL_NAME(sys_rt_sigtimedwait) + .long SYMBOL_NAME(sys_rt_sigqueueinfo) + .long SYMBOL_NAME(sys_rt_sigsuspend) + .long SYMBOL_NAME(sys_pread) /* 180 */ + .long SYMBOL_NAME(sys_pwrite) + + .rept NR_syscalls-181 .long SYMBOL_NAME(sys_ni_syscall) .endr diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S index 00a8e122e..a21ac6791 100644 --- a/arch/i386/kernel/head.S +++ b/arch/i386/kernel/head.S @@ -29,7 +29,7 @@ startup_32: * Set segments to known values */ cld - movl $(KERNEL_DS),%eax + movl $(__KERNEL_DS),%eax mov %ax,%ds mov %ax,%es mov %ax,%fs @@ -227,14 +227,14 @@ is386: pushl %ecx # restore original EFLAGS #endif lgdt gdt_descr lidt idt_descr - ljmp $(KERNEL_CS),$1f -1: movl $(KERNEL_DS),%eax # reload all the segment registers + ljmp $(__KERNEL_CS),$1f +1: movl $(__KERNEL_DS),%eax# reload all the segment registers mov %ax,%ds # after changing gdt. mov %ax,%es mov %ax,%fs mov %ax,%gs #ifdef __SMP__ - movl $(KERNEL_DS), %eax + movl $(__KERNEL_DS), %eax mov %ax,%ss # Reload the stack pointer (segment only) #else lss stack_start,%esp # Load processor stack @@ -285,7 +285,7 @@ check_x87: */ setup_idt: lea ignore_int,%edx - movl $(KERNEL_CS << 16),%eax + movl $(__KERNEL_CS << 16),%eax movw %dx,%ax /* selector = 0x0010 = cs */ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ @@ -301,7 +301,7 @@ rp_sidt: ENTRY(stack_start) .long SYMBOL_NAME(init_task_union)+8192 - .long KERNEL_DS + .long __KERNEL_DS /* This is the default interrupt "handler" :-) */ int_msg: @@ -314,7 +314,7 @@ ignore_int: pushl %edx push %es push %ds - movl $(KERNEL_DS),%eax + movl $(__KERNEL_DS),%eax mov %ax,%ds mov %ax,%es pushl $int_msg diff --git a/arch/i386/kernel/init_task.c b/arch/i386/kernel/init_task.c index cc0a19231..acc206942 100644 --- a/arch/i386/kernel/init_task.c +++ b/arch/i386/kernel/init_task.c @@ -1,6 +1,7 @@ #include <linux/mm.h> #include <linux/sched.h> +#include <asm/uaccess.h> #include <asm/pgtable.h> static struct vm_area_struct init_mmap = INIT_MMAP; diff --git a/arch/i386/kernel/irq.h b/arch/i386/kernel/irq.h index 7d70264ba..db70872f1 100644 --- a/arch/i386/kernel/irq.h +++ b/arch/i386/kernel/irq.h @@ -44,7 +44,7 @@ static inline void irq_exit(int cpu, int irq) "pushl %edx\n\t" \ "pushl %ecx\n\t" \ "pushl %ebx\n\t" \ - "movl $" STR(KERNEL_DS) ",%edx\n\t" \ + "movl $" STR(__KERNEL_DS) ",%edx\n\t" \ "mov %dx,%ds\n\t" \ "mov %dx,%es\n\t" diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index a8fe0315b..5a13e0179 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -281,22 +281,19 @@ void machine_restart(char * __unused) { if(!reboot_thru_bios) { -#if 0 - sti(); -#endif /* rebooting needs to touch the page at absolute addr 0 */ *((unsigned short *)__va(0x472)) = reboot_mode; for (;;) { int i; for (i=0; i<100; i++) { - int j; kb_wait(); - for(j = 0; j < 100000 ; j++) - /* nothing */; + udelay(10); outb(0xfe,0x64); /* pulse reset low */ udelay(10); } - __asm__ __volatile__("\tlidt %0": "=m" (no_idt)); + /* That didn't work - force a triple fault.. */ + __asm__ __volatile__("lidt %0": :"m" (no_idt)); + __asm__ __volatile__("int3"); } } @@ -480,13 +477,13 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, p->tss.tr = _TSS(nr); p->tss.ldt = _LDT(nr); - p->tss.es = KERNEL_DS; - p->tss.cs = KERNEL_CS; - p->tss.ss = KERNEL_DS; - p->tss.ds = KERNEL_DS; - p->tss.fs = USER_DS; - p->tss.gs = USER_DS; - p->tss.ss0 = KERNEL_DS; + p->tss.es = __KERNEL_DS; + p->tss.cs = __KERNEL_CS; + p->tss.ss = __KERNEL_DS; + p->tss.ds = __KERNEL_DS; + p->tss.fs = __USER_DS; + p->tss.gs = __USER_DS; + p->tss.ss0 = __KERNEL_DS; p->tss.esp0 = 2*PAGE_SIZE + (unsigned long) p; childregs = ((struct pt_regs *) (p->tss.esp0)) - 1; p->tss.esp = (unsigned long) childregs; diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c index c8a7f986e..246a6c29b 100644 --- a/arch/i386/kernel/ptrace.c +++ b/arch/i386/kernel/ptrace.c @@ -492,7 +492,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) long tmp; ret = -EIO; - if ((unsigned long) data > NSIG) + if ((unsigned long) data > _NSIG) goto out; if (request == PTRACE_SYSCALL) child->flags |= PF_TRACESYS; @@ -530,7 +530,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) long tmp; ret = -EIO; - if ((unsigned long) data > NSIG) + if ((unsigned long) data > _NSIG) goto out; child->flags &= ~PF_TRACESYS; tmp = get_stack_long(child, EFL_OFFSET) | TRAP_FLAG; @@ -546,7 +546,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) long tmp; ret = -EIO; - if ((unsigned long) data > NSIG) + if ((unsigned long) data > _NSIG) goto out; child->flags &= ~(PF_PTRACED|PF_TRACESYS); wake_up_process(child); @@ -585,9 +585,7 @@ asmlinkage void syscall_trace(void) * stopping signal is not SIGTRAP. -brl */ if (current->exit_code) { - spin_lock_irq(¤t->sigmask_lock); - current->signal |= (1 << (current->exit_code - 1)); - spin_unlock_irq(¤t->sigmask_lock); + send_sig(current->exit_code, current, 1); + current->exit_code = 0; } - current->exit_code = 0; } diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c index f5af47201..7d5cf3a95 100644 --- a/arch/i386/kernel/signal.c +++ b/arch/i386/kernel/signal.c @@ -2,6 +2,8 @@ * linux/arch/i386/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds + * + * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson */ #include <linux/config.h> @@ -16,40 +18,132 @@ #include <linux/wait.h> #include <linux/ptrace.h> #include <linux/unistd.h> - +#include <linux/stddef.h> +#include <asm/ucontext.h> #include <asm/uaccess.h> -#define _S(nr) (1<<((nr)-1)) +#define DEBUG_SIG 0 -#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr, int options, unsigned long *ru); - -asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs); +asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs); /* - * atomically swap in the new signal mask, and wait for a signal. + * Atomically swap in the new signal mask, and wait for a signal. */ -asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, unsigned long set) +asmlinkage int +sys_sigsuspend(int history0, int history1, old_sigset_t mask) { - struct pt_regs * regs = (struct pt_regs *) &restart; - unsigned long mask; + struct pt_regs * regs = (struct pt_regs *) &history0; + sigset_t saveset; + mask &= _BLOCKABLE; spin_lock_irq(¤t->sigmask_lock); - mask = current->blocked; - current->blocked = set & _BLOCKABLE; + saveset = current->blocked; + siginitset(¤t->blocked, mask); + recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); regs->eax = -EINTR; while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); - if (do_signal(mask, regs)) + if (do_signal(&saveset, regs)) return -EINTR; } } +asmlinkage int +sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize) +{ + struct pt_regs * regs = (struct pt_regs *) &unewset; + sigset_t saveset, newset; + + /* XXX: Don't preclude handling different sized sigset_t's. */ + if (sigsetsize != sizeof(sigset_t)) + return -EINVAL; + + 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->eax = -EINTR; + while (1) { + current->state = TASK_INTERRUPTIBLE; + schedule(); + if (do_signal(&saveset, regs)) + return -EINTR; + } +} + +asmlinkage int +sys_sigaction(int sig, const struct old_sigaction *act, + struct old_sigaction *oact) +{ + struct k_sigaction new_ka, old_ka; + int ret; + + if (act) { + old_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_restorer, &act->sa_restorer)) + return -EFAULT; + __get_user(new_ka.sa.sa_flags, &act->sa_flags); + __get_user(mask, &act->sa_mask); + 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_restorer, &oact->sa_restorer)) + return -EFAULT; + __put_user(old_ka.sa.sa_flags, &oact->sa_flags); + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); + } + + return ret; +} + + +/* + * Do a signal return; undo the signal stack. + */ + +struct sigframe +{ + char *pretcode; + int sig; + struct sigcontext sc; + struct _fpstate fpstate; + unsigned long extramask[_NSIG_WORDS-1]; + char retcode[8]; +}; + +struct rt_sigframe +{ + char *pretcode; + int sig; + struct siginfo *pinfo; + void *puc; + struct siginfo info; + struct ucontext uc; + struct _fpstate fpstate; + char retcode[8]; +}; + + static inline void restore_i387_hard(struct _fpstate *buf) { #ifdef __SMP__ @@ -64,94 +158,150 @@ static inline void restore_i387_hard(struct _fpstate *buf) #endif current->used_math = 1; current->flags &= ~PF_USEDFPU; - copy_from_user(¤t->tss.i387.hard, buf, sizeof(*buf)); + __copy_from_user(¤t->tss.i387.hard, buf, sizeof(*buf)); } -static void restore_i387(struct _fpstate *buf) +static inline void restore_i387(struct _fpstate *buf) { #ifndef CONFIG_MATH_EMULATION restore_i387_hard(buf); #else - if (hard_math) { + if (hard_math) restore_i387_hard(buf); - return; - } - restore_i387_soft(buf); -#endif + else + restore_i387_soft(buf); +#endif } - -/* - * This sets regs->esp even though we don't actually use sigstacks yet.. - */ -asmlinkage int sys_sigreturn(unsigned long __unused) +static int +restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) { -#define COPY(x) regs->x = context->x -#define COPY_SEG(seg) \ -{ unsigned int tmp = context->seg; \ -if ( (tmp & 0xfffc) /* not a NULL selectors */ \ - && (tmp & 0x4) != 0x4 /* not a LDT selector */ \ - && (tmp & 3) != 3 /* not a RPL3 GDT selector */ \ - ) goto badframe; \ -regs->x##seg = tmp; } -#define COPY_SEG_STRICT(seg) \ -{ unsigned int tmp = context->seg; \ -if ((tmp & 0xfffc) && (tmp & 3) != 3) goto badframe; \ -regs->x##seg = tmp; } -#define GET_SEG(seg) \ -{ unsigned int tmp = context->seg; \ -if ( (tmp & 0xfffc) /* not a NULL selectors */ \ - && (tmp & 0x4) != 0x4 /* not a LDT selector */ \ - && (tmp & 3) != 3 /* not a RPL3 GDT selector */ \ - ) goto badframe; \ -__asm__("mov %w0,%%" #seg: :"r" (tmp)); } - struct sigcontext * context; - struct pt_regs * regs; - - regs = (struct pt_regs *) &__unused; - context = (struct sigcontext *) regs->esp; - if (verify_area(VERIFY_READ, context, sizeof(*context))) - goto badframe; - current->blocked = context->oldmask & _BLOCKABLE; - COPY_SEG(ds); - COPY_SEG(es); - GET_SEG(fs); + unsigned int tmp; + +#define COPY(x) __get_user(regs->x, &sc->x) + +#define COPY_SEG(seg) \ + { __get_user(tmp, &sc->seg); \ + if ((tmp & 0xfffc) /* not a NULL selectors */ \ + && (tmp & 0x4) != 0x4 /* not a LDT selector */ \ + && (tmp & 3) != 3) /* not a RPL3 GDT selector */ \ + goto badframe; \ + regs->x##seg = tmp; } + +#define COPY_SEG_STRICT(seg) \ + { __get_user(tmp, &sc->seg); \ + if ((tmp & 0xfffc) && (tmp & 3) != 3) goto badframe; \ + regs->x##seg = tmp; } + +#define GET_SEG(seg) \ + { __get_user(tmp, &sc->seg); \ + if ((tmp & 0xfffc) /* not a NULL selectors */ \ + && (tmp & 0x4) != 0x4 /* not a LDT selector */ \ + && (tmp & 3) != 3) /* not a RPL3 GDT selector */ \ + goto badframe; \ + __asm__ __volatile__("mov %w0,%%" #seg : : "r"(tmp)); } + GET_SEG(gs); - COPY_SEG_STRICT(ss); - COPY_SEG_STRICT(cs); - COPY(eip); - COPY(ecx); COPY(edx); + GET_SEG(fs); + COPY_SEG(es); + COPY_SEG(ds); + COPY(edi); + COPY(esi); + COPY(ebp); + COPY(esp); COPY(ebx); - COPY(esp); COPY(ebp); - COPY(edi); COPY(esi); - regs->eflags &= ~0x40DD5; - regs->eflags |= context->eflags & 0x40DD5; + COPY(edx); + COPY(ecx); + COPY(eip); + COPY_SEG_STRICT(cs); + COPY_SEG_STRICT(ss); + + __get_user(tmp, &sc->eflags); + regs->eflags = (regs->eflags & ~0x40DD5) | (tmp & 0x40DD5); regs->orig_eax = -1; /* disable syscall checks */ - if (context->fpstate) { - struct _fpstate * buf = context->fpstate; + + __get_user(tmp, (unsigned long *)&sc->fpstate); + if (tmp) { + struct _fpstate * buf = (struct _fpstate *) tmp; if (verify_area(VERIFY_READ, buf, sizeof(*buf))) goto badframe; restore_i387(buf); } - return context->eax; + + __get_user(tmp, &sc->eax); + return tmp; badframe: lock_kernel(); do_exit(SIGSEGV); - unlock_kernel(); } +asmlinkage int sys_sigreturn(unsigned long __unused) +{ + struct pt_regs *regs = (struct pt_regs *) &__unused; + struct sigframe *frame = (struct sigframe *)(regs->esp - 8); + sigset_t set; + + if (verify_area(VERIFY_READ, frame, sizeof(*frame))) + goto badframe; + if (__get_user(set.sig[0], &frame->sc.oldmask) + || (_NSIG_WORDS > 1 + && __copy_from_user(&set.sig[1], &frame->extramask, + sizeof(frame->extramask)))) + goto badframe; + + sigdelsetmask(&set, ~_BLOCKABLE); + spin_lock_irq(¤t->sigmask_lock); + current->blocked = set; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + + return restore_sigcontext(regs, &frame->sc); + +badframe: + lock_kernel(); + do_exit(SIGSEGV); +} + +asmlinkage int sys_rt_sigreturn(unsigned long __unused) +{ + struct pt_regs *regs = (struct pt_regs *) &__unused; + struct rt_sigframe *frame = (struct rt_sigframe *)(regs->esp - 4); + sigset_t set; + + if (verify_area(VERIFY_READ, frame, sizeof(*frame))) + goto badframe; + if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) + goto badframe; + + sigdelsetmask(&set, ~_BLOCKABLE); + spin_lock_irq(¤t->sigmask_lock); + current->blocked = set; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + + return restore_sigcontext(regs, &frame->uc.uc_mcontext); + +badframe: + lock_kernel(); + do_exit(SIGSEGV); +} + +/* + * Set up a signal frame. + */ + static inline struct _fpstate * save_i387_hard(struct _fpstate * buf) { #ifdef __SMP__ if (current->flags & PF_USEDFPU) { - __asm__ __volatile__("fnsave %0":"=m" (current->tss.i387.hard)); + __asm__ __volatile__("fnsave %0":"=m"(current->tss.i387.hard)); stts(); current->flags &= ~PF_USEDFPU; } #else if (current == last_task_used_math) { - __asm__ __volatile__("fnsave %0":"=m" (current->tss.i387.hard)); + __asm__ __volatile__("fnsave %0":"=m"(current->tss.i387.hard)); last_task_used_math = NULL; __asm__ __volatile__("fwait"); /* not needed on 486+ */ stts(); @@ -163,7 +313,7 @@ static inline struct _fpstate * save_i387_hard(struct _fpstate * buf) return buf; } -static struct _fpstate * save_i387(struct _fpstate * buf) +static struct _fpstate * save_i387(struct _fpstate *buf) { if (!current->used_math) return NULL; @@ -171,107 +321,197 @@ static struct _fpstate * save_i387(struct _fpstate * buf) #ifndef CONFIG_MATH_EMULATION return save_i387_hard(buf); #else - if (hard_math) - return save_i387_hard(buf); - return save_i387_soft(buf); + return hard_math ? save_i387_hard(buf) : save_i387_soft(buf); #endif } -/* - * Set up a signal frame... Make the stack look the way iBCS2 expects - * it to look. - */ -static void setup_frame(struct sigaction * sa, - struct pt_regs * regs, int signr, - unsigned long oldmask) +static void +setup_sigcontext(struct sigcontext *sc, struct _fpstate *fpstate, + struct pt_regs *regs, unsigned long mask) { - unsigned long * frame; + unsigned int tmp; + + tmp = 0; + __asm__("mov %%gs,%w0" : "=r"(tmp): "0"(tmp)); + __put_user(tmp, (unsigned int *)&sc->gs); + __asm__("mov %%fs,%w0" : "=r"(tmp): "0"(tmp)); + __put_user(tmp, (unsigned int *)&sc->fs); + + __put_user(regs->xes, (unsigned int *)&sc->es); + __put_user(regs->xds, (unsigned int *)&sc->ds); + __put_user(regs->edi, &sc->edi); + __put_user(regs->esi, &sc->esi); + __put_user(regs->ebp, &sc->ebp); + __put_user(regs->esp, &sc->esp); + __put_user(regs->ebx, &sc->ebx); + __put_user(regs->edx, &sc->edx); + __put_user(regs->ecx, &sc->ecx); + __put_user(regs->eax, &sc->eax); + __put_user(current->tss.trap_no, &sc->trapno); + __put_user(current->tss.error_code, &sc->err); + __put_user(regs->eip, &sc->eip); + __put_user(regs->xcs, (unsigned int *)&sc->cs); + __put_user(regs->eflags, &sc->eflags); + __put_user(regs->esp, &sc->esp_at_signal); + __put_user(regs->xss, (unsigned int *)&sc->ss); + + __put_user(save_i387(fpstate), &sc->fpstate); + + /* non-iBCS2 extensions.. */ + __put_user(mask, &sc->oldmask); + __put_user(current->tss.cr2, &sc->cr2); +} + +static void setup_frame(int sig, struct k_sigaction *ka, + sigset_t *set, struct pt_regs * regs) +{ + struct sigframe *frame; - frame = (unsigned long *) regs->esp; - if ((regs->xss & 0xffff) != USER_DS && sa->sa_restorer) - frame = (unsigned long *) sa->sa_restorer; - frame -= 64; - if (!access_ok(VERIFY_WRITE,frame,64*4)) - goto segv_and_exit; + frame = (struct sigframe *)((regs->esp - sizeof(*frame)) & -8); -/* set up the "normal" stack seen by the signal handler (iBCS2) */ -#define __CODE ((unsigned long)(frame+24)) -#define CODE(x) ((unsigned long *) ((x)+__CODE)) - - /* XXX Can possible miss a SIGSEGV when frame crosses a page border - and a thread unmaps it while we are accessing it. - So either check all put_user() calls or don't do it at all. - We use __put_user() here because the access_ok() call was already - done earlier. */ - if (__put_user(__CODE,frame)) + /* XXX: Check here if we need to switch stacks.. */ + + /* This is legacy signal stack switching. */ + if ((regs->xss & 0xffff) != __USER_DS + && !(ka->sa.sa_flags & SA_RESTORER) && ka->sa.sa_restorer) + frame = (struct sigframe *) ka->sa.sa_restorer; + + if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto segv_and_exit; - if (current->exec_domain && current->exec_domain->signal_invmap) - __put_user(current->exec_domain->signal_invmap[signr], frame+1); - else - __put_user(signr, frame+1); + + __put_user((current->exec_domain + && current->exec_domain->signal_invmap + && sig < 32 + ? current->exec_domain->signal_invmap[sig] + : sig), + &frame->sig); + + setup_sigcontext(&frame->sc, &frame->fpstate, regs, set->sig[0]); + + if (_NSIG_WORDS > 1) { + __copy_to_user(frame->extramask, &set->sig[1], + sizeof(frame->extramask)); + } + + /* Set up to return from userspace. If provided, use a stub + already in userspace. */ + if (ka->sa.sa_flags & SA_RESTORER) { + __put_user(ka->sa.sa_restorer, &frame->pretcode); + } else { + __put_user(frame->retcode, &frame->pretcode); + /* This is popl %eax ; movl $,%eax ; int $0x80 */ + __put_user(0xb858, (short *)(frame->retcode+0)); + __put_user(__NR_sigreturn, (int *)(frame->retcode+2)); + __put_user(0x80cd, (short *)(frame->retcode+6)); + } + + /* Set up registers for signal handler */ + regs->esp = (unsigned long) frame; + regs->eip = (unsigned long) ka->sa.sa_handler; { - unsigned int tmp = 0; -#define PUT_SEG(seg, mem) \ -__asm__("mov %%" #seg",%w0":"=r" (tmp):"0" (tmp)); __put_user(tmp,mem); - PUT_SEG(gs, frame+2); - PUT_SEG(fs, frame+3); + unsigned long seg = __USER_DS; + __asm__("mov %w0,%%fs ; mov %w0,%%gs": "=r"(seg) : "0"(seg)); + set_fs(MAKE_MM_SEG(seg)); + regs->xds = seg; + regs->xes = seg; + regs->xss = seg; + regs->xcs = __USER_CS; + } + regs->eflags &= ~TF_MASK; + +#if DEBUG_SIG + printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", + current->comm, current->pid, frame, regs->eip, frame->pretcode); +#endif + + return; + +segv_and_exit: + lock_kernel(); + do_exit(SIGSEGV); +} + +static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, + sigset_t *set, struct pt_regs * regs) +{ + struct rt_sigframe *frame; + + frame = (struct rt_sigframe *)((regs->esp - sizeof(*frame)) & -8); + + /* XXX: Check here if we need to switch stacks.. */ + + /* This is legacy signal stack switching. */ + if ((regs->xss & 0xffff) != __USER_DS + && !(ka->sa.sa_flags & SA_RESTORER) && ka->sa.sa_restorer) + frame = (struct rt_sigframe *) ka->sa.sa_restorer; + + if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) + goto segv_and_exit; + + __put_user((current->exec_domain + && current->exec_domain->signal_invmap + && sig < 32 + ? current->exec_domain->signal_invmap[sig] + : sig), + &frame->sig); + __put_user(&frame->info, &frame->pinfo); + __put_user(&frame->uc, &frame->puc); + __copy_to_user(&frame->info, info, sizeof(*info)); + + /* Clear all the bits of the ucontext we don't use. */ + __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext)); + + setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate, + regs, set->sig[0]); + __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); + + /* Set up to return from userspace. If provided, use a stub + already in userspace. */ + if (ka->sa.sa_flags & SA_RESTORER) { + __put_user(ka->sa.sa_restorer, &frame->pretcode); + } else { + __put_user(frame->retcode, &frame->pretcode); + /* This is movl $,%eax ; int $0x80 */ + __put_user(0xb8, (char *)(frame->retcode+0)); + __put_user(__NR_rt_sigreturn, (int *)(frame->retcode+1)); + __put_user(0x80cd, (short *)(frame->retcode+5)); } - __put_user(regs->xes, frame+4); - __put_user(regs->xds, frame+5); - __put_user(regs->edi, frame+6); - __put_user(regs->esi, frame+7); - __put_user(regs->ebp, frame+8); - __put_user(regs->esp, frame+9); - __put_user(regs->ebx, frame+10); - __put_user(regs->edx, frame+11); - __put_user(regs->ecx, frame+12); - __put_user(regs->eax, frame+13); - __put_user(current->tss.trap_no, frame+14); - __put_user(current->tss.error_code, frame+15); - __put_user(regs->eip, frame+16); - __put_user(regs->xcs, frame+17); - __put_user(regs->eflags, frame+18); - __put_user(regs->esp, frame+19); - __put_user(regs->xss, frame+20); - __put_user((unsigned long) save_i387((struct _fpstate *)(frame+32)),frame+21); -/* non-iBCS2 extensions.. */ - __put_user(oldmask, frame+22); - __put_user(current->tss.cr2, frame+23); -/* set up the return code... */ - __put_user(0x0000b858, CODE(0)); /* popl %eax ; movl $,%eax */ - __put_user(0x80cd0000, CODE(4)); /* int $0x80 */ - __put_user(__NR_sigreturn, CODE(2)); -#undef __CODE -#undef CODE /* Set up registers for signal handler */ regs->esp = (unsigned long) frame; - regs->eip = (unsigned long) sa->sa_handler; + regs->eip = (unsigned long) ka->sa.sa_handler; { - unsigned long seg = USER_DS; - __asm__("mov %w0,%%fs ; mov %w0,%%gs":"=r" (seg) :"0" (seg)); - set_fs(seg); + unsigned long seg = __USER_DS; + __asm__("mov %w0,%%fs ; mov %w0,%%gs": "=r"(seg) : "0"(seg)); + set_fs(MAKE_MM_SEG(seg)); regs->xds = seg; regs->xes = seg; regs->xss = seg; - regs->xcs = USER_CS; + regs->xcs = __USER_CS; } regs->eflags &= ~TF_MASK; + +#if DEBUG_SIG + printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", + current->comm, current->pid, frame, regs->eip, frame->pretcode); +#endif + return; segv_and_exit: lock_kernel(); do_exit(SIGSEGV); - unlock_kernel(); } /* * OK, we're invoking a handler */ -static void handle_signal(unsigned long signr, struct sigaction *sa, - unsigned long oldmask, struct pt_regs * regs) + +static void +handle_signal(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) { - /* are we from a system call? */ + /* Are we from a system call? */ if (regs->orig_eax >= 0) { /* If so, check system call restarting.. */ switch (regs->eax) { @@ -280,7 +520,7 @@ static void handle_signal(unsigned long signr, struct sigaction *sa, break; case -ERESTARTSYS: - if (!(sa->sa_flags & SA_RESTART)) { + if (!(ka->sa.sa_flags & SA_RESTART)) { regs->eax = -EINTR; break; } @@ -291,14 +531,20 @@ static void handle_signal(unsigned long signr, struct sigaction *sa, } } - /* set up the stack frame */ - setup_frame(sa, regs, signr, oldmask); + /* Set up the stack frame */ + if (ka->sa.sa_flags & SA_SIGINFO) + setup_rt_frame(sig, ka, info, oldset, regs); + else + setup_frame(sig, ka, oldset, regs); + + if (ka->sa.sa_flags & SA_ONESHOT) + ka->sa.sa_handler = SIG_DFL; - if (sa->sa_flags & SA_ONESHOT) - sa->sa_handler = NULL; - if (!(sa->sa_flags & SA_NOMASK)) { + if (!(ka->sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sigmask_lock); - current->blocked |= (sa->sa_mask | _S(signr)) & _BLOCKABLE; + sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigaddset(¤t->blocked,sig); + recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); } } @@ -312,66 +558,82 @@ static void handle_signal(unsigned long signr, struct sigaction *sa, * the kernel can handle, and then we build all the user-level signal handling * stack-frames in one go after that. */ -asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs) +asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) { - unsigned long mask; - unsigned long signr; - struct sigaction * sa; + siginfo_t info; + struct k_sigaction *ka; /* - * We want the common case to go fast, which + * We want the common case to go fast, which * is why we may in certain cases get here from * kernel mode. Just return without doing anything * if so. */ if ((regs->xcs & 3) != 3) return 1; - mask = ~current->blocked; - while ((signr = current->signal & mask)) { - /* - * This stops gcc flipping out. Otherwise the assembler - * including volatiles for the inline function to get - * current combined with this gets it confused. - */ - struct task_struct *t=current; - __asm__("bsf %3,%1\n\t" -#ifdef __SMP__ - "lock ; " -#endif - "btrl %1,%0" - :"=m" (t->signal),"=r" (signr) - :"0" (t->signal), "1" (signr)); - sa = current->sig->action + signr; - signr++; + + if (!oldset) + oldset = ¤t->blocked; + + for (;;) { + unsigned long signr; + + spin_lock_irq(¤t->sigmask_lock); + signr = dequeue_signal(¤t->blocked, &info); + spin_unlock_irq(¤t->sigmask_lock); + + if (!signr) + break; + if ((current->flags & PF_PTRACED) && signr != SIGKILL) { + /* Let the debugger run. */ current->exit_code = signr; current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); + + /* We're back. Did the debugger cancel the sig? */ if (!(signr = current->exit_code)) continue; current->exit_code = 0; + + /* The debugger continued. Ignore SIGSTOP. */ if (signr == SIGSTOP) continue; - if (_S(signr) & current->blocked) { - spin_lock_irq(¤t->sigmask_lock); - current->signal |= _S(signr); - spin_unlock_irq(¤t->sigmask_lock); + + /* Update the siginfo structure. Is this good? */ + if (signr != info.si_signo) { + info.si_signo = signr; + info.si_errno = 0; + info.si_code = SI_USER; + info.si_pid = current->p_pptr->pid; + info.si_uid = current->p_pptr->uid; + } + + /* If the (new) signal is now blocked, requeue it. */ + if (sigismember(¤t->blocked, signr)) { + send_sig_info(signr, &info, current); continue; } - sa = current->sig->action + signr - 1; } - if (sa->sa_handler == SIG_IGN) { + + ka = ¤t->sig->action[signr-1]; + if (ka->sa.sa_handler == SIG_IGN) { if (signr != SIGCHLD) continue; - /* check for SIGCHLD: it's special */ - while (sys_wait4(-1,NULL,WNOHANG, NULL) > 0) + /* Check for SIGCHLD: it's special. */ + while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0) /* nothing */; continue; } - if (sa->sa_handler == SIG_DFL) { + + if (ka->sa.sa_handler == SIG_DFL) { + int exit_code = signr; + + /* Init gets no signals it doesn't want. */ if (current->pid == 1) continue; + switch (signr) { case SIGCONT: case SIGCHLD: case SIGWINCH: continue; @@ -379,13 +641,12 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs) case SIGTSTP: case SIGTTIN: case SIGTTOU: if (is_orphaned_pgrp(current->pgrp)) continue; + /* FALLTHRU */ + case SIGSTOP: - if (current->flags & PF_PTRACED) - continue; current->state = TASK_STOPPED; current->exit_code = signr; - if (!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags & - SA_NOCLDSTOP)) + if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) notify_parent(current, SIGCHLD); schedule(); continue; @@ -393,25 +654,24 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs) case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: lock_kernel(); - if (current->binfmt && current->binfmt->core_dump) { - if (current->binfmt->core_dump(signr, regs)) - signr |= 0x80; - } + if (current->binfmt + && current->binfmt->core_dump + && current->binfmt->core_dump(signr, regs)) + exit_code |= 0x80; unlock_kernel(); - /* fall through */ - default: - spin_lock_irq(¤t->sigmask_lock); - current->signal |= _S(signr & 0x7f); - spin_unlock_irq(¤t->sigmask_lock); + /* FALLTHRU */ + default: + lock_kernel(); + sigaddset(¤t->signal, signr); current->flags |= PF_SIGNALED; - - lock_kernel(); /* 8-( */ - do_exit(signr); - unlock_kernel(); + do_exit(exit_code); + /* NOTREACHED */ } } - handle_signal(signr, sa, oldmask, regs); + + /* Whee! Actually deliver the signal. */ + handle_signal(signr, ka, &info, oldset, regs); return 1; } diff --git a/arch/i386/kernel/sys_i386.c b/arch/i386/kernel/sys_i386.c index f43dfe726..80ef4be47 100644 --- a/arch/i386/kernel/sys_i386.c +++ b/arch/i386/kernel/sys_i386.c @@ -180,7 +180,7 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, } case 1: /* iBCS2 emulator entry point */ ret = -EINVAL; - if (get_fs() != get_ds()) + if (!segment_eq(get_fs(), get_ds())) goto out; ret = sys_shmat (first, (char *) ptr, second, (ulong *) third); goto out; @@ -225,15 +225,16 @@ asmlinkage int sys_olduname(struct oldold_utsname * name) return -EFAULT; error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN); - error -= __put_user(0,name->sysname+__OLD_UTS_LEN); - error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN); - error -= __put_user(0,name->nodename+__OLD_UTS_LEN); - error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN); - error -= __put_user(0,name->release+__OLD_UTS_LEN); - error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN); - error -= __put_user(0,name->version+__OLD_UTS_LEN); - error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN); - error = __put_user(0,name->machine+__OLD_UTS_LEN); + error |= __put_user(0,name->sysname+__OLD_UTS_LEN); + error |= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN); + error |= __put_user(0,name->nodename+__OLD_UTS_LEN); + error |= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN); + error |= __put_user(0,name->release+__OLD_UTS_LEN); + error |= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN); + error |= __put_user(0,name->version+__OLD_UTS_LEN); + error |= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN); + error |= __put_user(0,name->machine+__OLD_UTS_LEN); + error = error ? -EFAULT : 0; return error; diff --git a/arch/i386/kernel/trampoline.S b/arch/i386/kernel/trampoline.S index f44b9abde..9cee704f1 100644 --- a/arch/i386/kernel/trampoline.S +++ b/arch/i386/kernel/trampoline.S @@ -53,7 +53,7 @@ r_base = . lmsw %ax # into protected mode jmp flush_instr flush_instr: - ljmp $KERNEL_CS, $0x00100000 + ljmp $__KERNEL_CS, $0x00100000 # jump to startup_32 idt_48: diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index f08b7de6b..bd125a041 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -127,7 +127,7 @@ static void show_registers(struct pt_regs *regs) extern char _stext, _etext; esp = (unsigned long) ®s->esp; - ss = KERNEL_DS; + ss = __KERNEL_DS; if (regs->xcs & 3) { esp = regs->esp; ss = regs->xss & 0xffff; @@ -184,7 +184,7 @@ static void show_registers(struct pt_regs *regs) spinlock_t die_lock; -/*static*/ void die_if_kernel(const char * str, struct pt_regs * regs, long err) +void die_if_kernel(const char * str, struct pt_regs * regs, long err) { if ((regs->eflags & VM_MASK) || (3 & regs->xcs) == 3) return; diff --git a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c index a09fa6419..0628e2d68 100644 --- a/arch/i386/kernel/vm86.c +++ b/arch/i386/kernel/vm86.c @@ -438,8 +438,13 @@ int handle_vm86_trap(struct kernel_vm86_regs * regs, long error_code, int trapno } if (trapno !=1) return 1; /* we let this handle by the calling routine */ - if (current->flags & PF_PTRACED) - current->blocked &= ~(1 << (SIGTRAP-1)); + if (current->flags & PF_PTRACED) { + unsigned long flags; + spin_lock_irqsave(¤t->sigmask_lock, flags); + sigdelset(¤t->blocked, SIGTRAP); + recalc_sigpending(current); + spin_unlock_irqrestore(¤t->sigmask_lock, flags); + } send_sig(SIGTRAP, current, 1); current->tss.trap_no = trapno; current->tss.error_code = error_code; diff --git a/arch/i386/lib/delay.c b/arch/i386/lib/delay.c index c3c29a7d9..4afc206e5 100644 --- a/arch/i386/lib/delay.c +++ b/arch/i386/lib/delay.c @@ -9,7 +9,7 @@ */ #include <linux/sched.h> -#include <asm/delay.h> +#include <linux/delay.h> #ifdef __SMP__ #include <asm/smp.h> diff --git a/arch/i386/math-emu/errors.c b/arch/i386/math-emu/errors.c index f76020d1f..38a72e572 100644 --- a/arch/i386/math-emu/errors.c +++ b/arch/i386/math-emu/errors.c @@ -42,7 +42,7 @@ void Un_impl(void) RE_ENTRANT_CHECK_OFF; /* No need to verify_area(), we have previously fetched these bytes. */ printk("Unimplemented FPU Opcode at eip=%p : ", (void *) address); - if ( FPU_CS == USER_CS ) + if ( FPU_CS == __USER_CS ) { while ( 1 ) { @@ -93,7 +93,7 @@ void emu_printall(void) RE_ENTRANT_CHECK_OFF; /* No need to verify_area(), we have previously fetched these bytes. */ printk("At %p:", (void *) address); - if ( FPU_CS == USER_CS ) + if ( FPU_CS == __USER_CS ) { #define MAX_PRINTED_BYTES 20 for ( i = 0; i < MAX_PRINTED_BYTES; i++ ) diff --git a/arch/i386/math-emu/fpu_entry.c b/arch/i386/math-emu/fpu_entry.c index 07c32db9a..943daf3b9 100644 --- a/arch/i386/math-emu/fpu_entry.c +++ b/arch/i386/math-emu/fpu_entry.c @@ -179,11 +179,11 @@ asmlinkage void math_emulate(long arg) FPU_EIP += code_base = FPU_CS << 4; code_limit = code_base + 0xffff; /* Assumes code_base <= 0xffff0000 */ } - else if ( FPU_CS == USER_CS && FPU_DS == USER_DS ) + else if ( FPU_CS == __USER_CS && FPU_DS == __USER_DS ) { addr_modes.default_mode = 0; } - else if ( FPU_CS == KERNEL_CS ) + else if ( FPU_CS == __KERNEL_CS ) { printk("math_emulate: %04x:%08lx\n",FPU_CS,FPU_EIP); panic("Math emulation needed in kernel"); |