summaryrefslogtreecommitdiffstats
path: root/arch/i386
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-12-16 05:34:03 +0000
committerRalf Baechle <ralf@linux-mips.org>1997-12-16 05:34:03 +0000
commit967c65a99059fd459b956c1588ce0ba227912c4e (patch)
tree8224d013ff5d255420713d05610c7efebd204d2a /arch/i386
parente20c1cc1656a66a2773bca4591a895cbc12696ff (diff)
Merge with Linux 2.1.72, part 1.
Diffstat (limited to 'arch/i386')
-rw-r--r--arch/i386/boot/compressed/head.S10
-rw-r--r--arch/i386/boot/compressed/misc.c2
-rw-r--r--arch/i386/boot/setup.S4
-rw-r--r--arch/i386/config.in13
-rw-r--r--arch/i386/defconfig23
-rw-r--r--arch/i386/kernel/bios32.c6
-rw-r--r--arch/i386/kernel/entry.S37
-rw-r--r--arch/i386/kernel/head.S14
-rw-r--r--arch/i386/kernel/init_task.c1
-rw-r--r--arch/i386/kernel/irq.h2
-rw-r--r--arch/i386/kernel/process.c25
-rw-r--r--arch/i386/kernel/ptrace.c12
-rw-r--r--arch/i386/kernel/signal.c654
-rw-r--r--arch/i386/kernel/sys_i386.c21
-rw-r--r--arch/i386/kernel/trampoline.S2
-rw-r--r--arch/i386/kernel/traps.c4
-rw-r--r--arch/i386/kernel/vm86.c9
-rw-r--r--arch/i386/lib/delay.c2
-rw-r--r--arch/i386/math-emu/errors.c4
-rw-r--r--arch/i386/math-emu/fpu_entry.c4
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(&current->sigmask_lock);
- current->signal |= (1 << (current->exit_code - 1));
- spin_unlock_irq(&current->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(&current->sigmask_lock);
- mask = current->blocked;
- current->blocked = set & _BLOCKABLE;
+ saveset = current->blocked;
+ siginitset(&current->blocked, mask);
+ recalc_sigpending(current);
spin_unlock_irq(&current->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(&current->sigmask_lock);
+ saveset = current->blocked;
+ current->blocked = newset;
+ recalc_sigpending(current);
+ spin_unlock_irq(&current->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(&current->tss.i387.hard, buf, sizeof(*buf));
+ __copy_from_user(&current->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(&current->sigmask_lock);
+ current->blocked = set;
+ recalc_sigpending(current);
+ spin_unlock_irq(&current->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(&current->sigmask_lock);
+ current->blocked = set;
+ recalc_sigpending(current);
+ spin_unlock_irq(&current->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(&current->sigmask_lock);
- current->blocked |= (sa->sa_mask | _S(signr)) & _BLOCKABLE;
+ sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+ sigaddset(&current->blocked,sig);
+ recalc_sigpending(current);
spin_unlock_irq(&current->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 = &current->blocked;
+
+ for (;;) {
+ unsigned long signr;
+
+ spin_lock_irq(&current->sigmask_lock);
+ signr = dequeue_signal(&current->blocked, &info);
+ spin_unlock_irq(&current->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(&current->sigmask_lock);
- current->signal |= _S(signr);
- spin_unlock_irq(&current->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(&current->blocked, signr)) {
+ send_sig_info(signr, &info, current);
continue;
}
- sa = current->sig->action + signr - 1;
}
- if (sa->sa_handler == SIG_IGN) {
+
+ ka = &current->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(&current->sigmask_lock);
- current->signal |= _S(signr & 0x7f);
- spin_unlock_irq(&current->sigmask_lock);
+ /* FALLTHRU */
+ default:
+ lock_kernel();
+ sigaddset(&current->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) &regs->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(&current->sigmask_lock, flags);
+ sigdelset(&current->blocked, SIGTRAP);
+ recalc_sigpending(current);
+ spin_unlock_irqrestore(&current->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");