summaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r--arch/mips/kernel/Makefile5
-rw-r--r--arch/mips/kernel/bios32.c7
-rw-r--r--arch/mips/kernel/entry.S49
-rw-r--r--arch/mips/kernel/gdb-low.S1
-rw-r--r--arch/mips/kernel/gdb-stub.c1
-rw-r--r--arch/mips/kernel/head.S1
-rw-r--r--arch/mips/kernel/ioport.c2
-rw-r--r--arch/mips/kernel/ipc.c97
-rw-r--r--arch/mips/kernel/irixelf.c117
-rw-r--r--arch/mips/kernel/irixioctl.c3
-rw-r--r--arch/mips/kernel/irixsig.c228
-rw-r--r--arch/mips/kernel/irq.c60
-rw-r--r--arch/mips/kernel/ksyms.c41
-rw-r--r--arch/mips/kernel/mips_ksyms.c44
-rw-r--r--arch/mips/kernel/pci.c177
-rw-r--r--arch/mips/kernel/process.c5
-rw-r--r--arch/mips/kernel/ptrace.c123
-rw-r--r--arch/mips/kernel/r2300_fpu.S1
-rw-r--r--arch/mips/kernel/r2300_misc.S1
-rw-r--r--arch/mips/kernel/r2300_scall.S4
-rw-r--r--arch/mips/kernel/r2300_switch.S1
-rw-r--r--arch/mips/kernel/r4k_misc.S2
-rw-r--r--arch/mips/kernel/r4k_scall.S4
-rw-r--r--arch/mips/kernel/r4k_switch.S2
-rw-r--r--arch/mips/kernel/reset.c30
-rw-r--r--arch/mips/kernel/setup.c10
-rw-r--r--arch/mips/kernel/signal.c125
-rw-r--r--arch/mips/kernel/syscall.c70
-rw-r--r--arch/mips/kernel/syscalls.h5
-rw-r--r--arch/mips/kernel/sysirix.c913
-rw-r--r--arch/mips/kernel/sysmips.c90
-rw-r--r--arch/mips/kernel/time.c84
-rw-r--r--arch/mips/kernel/traps.c97
-rw-r--r--arch/mips/kernel/unaligned.c28
34 files changed, 1592 insertions, 836 deletions
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index e537ac73e..b251d6e1a 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -6,8 +6,6 @@
# unless it's something special (ie not a .c file).
#
-.S.s:
- $(CPP) $(CFLAGS) $< -o $*.s
.S.o:
$(CC) $(CFLAGS) -c $< -o $*.o
@@ -15,9 +13,10 @@ all: kernel.o head.o
EXTRA_ASFLAGS = -mips3 -mcpu=r4000
O_TARGET := kernel.o
O_OBJS := branch.o process.o signal.o entry.o traps.o ptrace.o vm86.o \
- ioport.o setup.o syscall.o sysmips.o bios32.o ipc.o ksyms.o \
+ ioport.o pci.o reset.o setup.o syscall.o sysmips.o ipc.o \
r4k_switch.o r4k_misc.o r4k_scall.o r4k_fpu.o r2300_switch.o \
r2300_misc.o r2300_scall.o r2300_fpu.o r6000_fpu.o unaligned.o
+OX_OBJS := mips_ksyms.o
#
# SGI's have very different interrupt/timer hardware.
diff --git a/arch/mips/kernel/bios32.c b/arch/mips/kernel/bios32.c
deleted file mode 100644
index 1fe61faa0..000000000
--- a/arch/mips/kernel/bios32.c
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * bios 32 replacement
- */
-unsigned long bios32_init(unsigned long memory_start, unsigned long memory_end)
-{
- return memory_start;
-}
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index 515f9af13..8bb8fb41c 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -18,7 +18,6 @@
#include <asm/asm.h>
#include <asm/errno.h>
-#include <asm/segment.h>
#include <asm/mipsregs.h>
#include <asm/mipsconfig.h>
#include <asm/page.h>
@@ -30,18 +29,6 @@
#include <asm/unistd.h>
/*
- * These are offsets into the task-struct.
- */
-state = 0
-counter = 4
-priority = 8
-signal = 12
-blocked = 16
-flags = 20
-errno = 24
-exec_domain = 60
-
-/*
* Heia ... The %lo, %hi and %HI stuff is too strong for the ELF assembler
* and the ABI to cope with ...
*/
@@ -49,53 +36,40 @@ exec_domain = 60
.set noreorder
.set mips3
.align 4
+/* XXX cli/sti ??? */
handle_bottom_half:
- lui s0,%hi(intr_count)
- lw s1,%lo(intr_count)(s0)
mfc0 s3,CP0_STATUS # Enable IRQs
- addiu s2,s1, 1
- sw s2,%lo(intr_count)(s0)
ori t0,s3, 0x1f
xori t0,0x1e
jal do_bottom_half
mtc0 t0,CP0_STATUS
- mtc0 s3,CP0_STATUS # Restore old IRQ state
-
b 9f
- sw s1,%lo(intr_count)(s0)
+ mtc0 s3,CP0_STATUS # Restore old IRQ state
reschedule:
jal schedule
nop
EXPORT(ret_from_sys_call)
- lw t0,intr_count # bottom half
- bnez t0,return
-9:
+
lw t0,bh_mask
lw t1,bh_active # unused delay slot
and t0,t1
bnez t0,handle_bottom_half
- lw t0,PT_STATUS(sp) # returning to kernel mode?
+9: lw t0,PT_STATUS(sp) # returning to kernel mode?
andi t1,t0, 0x10
beqz t1,return # -> yes
- mfc0 t0,CP0_STATUS
-
- lw t1,need_resched
- ori t0,0x1f # enable irqs
- xori t0,0x1e
+ lw t1,need_resched
bnez t1,reschedule
- mtc0 t0,CP0_STATUS
-
- lw s0,current_set
+ lw s0,current_set
lw t0,task
- lw a0,blocked(s0)
+ lw a0,TASK_BLOCKED(s0)
beq s0,t0,return # task[0] cannot have signals
- lw t0,signal(s0) # save blocked in a0 for signals
+ lw t0,TASK_SIGNAL(s0)
nor t1,zero,a0
and t1,t0,t1
@@ -159,11 +133,7 @@ NESTED(fast_interrupt, PT_SIZE, sp)
* Don't return & unblock the pic
*/
LEAF(bad_interrupt)
- lw t0,%lo(intr_count)(s3)
- subu t0,1
-
j return
- sw t0,%lo(intr_count)(s3)
END(bad_interrupt)
.text
@@ -214,9 +184,8 @@ LEAF(spurious_interrupt)
.data; \
EXPORT(exception_count_##exception); \
.word 0; \
- .text;
+ .previous;
#define BUILD_HANDLER(exception,handler,clear,verbose) \
- .text; \
.align 5; \
NESTED(handle_##exception, PT_SIZE, sp); \
.set noat; \
diff --git a/arch/mips/kernel/gdb-low.S b/arch/mips/kernel/gdb-low.S
index 9bc35400b..6657bd77c 100644
--- a/arch/mips/kernel/gdb-low.S
+++ b/arch/mips/kernel/gdb-low.S
@@ -9,7 +9,6 @@
#include <linux/sys.h>
#include <asm/asm.h>
-#include <asm/segment.h>
#include <asm/mipsregs.h>
#include <asm/mipsconfig.h>
#include <asm/regdef.h>
diff --git a/arch/mips/kernel/gdb-stub.c b/arch/mips/kernel/gdb-stub.c
index 13bf353ff..255ec2228 100644
--- a/arch/mips/kernel/gdb-stub.c
+++ b/arch/mips/kernel/gdb-stub.c
@@ -70,7 +70,6 @@
#include <asm/asm.h>
#include <asm/mipsregs.h>
-#include <asm/segment.h>
#include <asm/cachectl.h>
#include <asm/system.h>
#include <asm/gdb-stub.h>
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index fa73c95bb..a957e16bd 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -15,7 +15,6 @@
#include <asm/offset.h>
#include <asm/processor.h>
#include <asm/regdef.h>
-#include <asm/segment.h>
#include <asm/cachectl.h>
#include <asm/mipsregs.h>
#include <asm/mipsconfig.h>
diff --git a/arch/mips/kernel/ioport.c b/arch/mips/kernel/ioport.c
index ff6c0d518..cc0581038 100644
--- a/arch/mips/kernel/ioport.c
+++ b/arch/mips/kernel/ioport.c
@@ -15,8 +15,6 @@ asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on)
return -ENOSYS;
}
-unsigned int *stack;
-
/*
* sys_iopl has to be used when you want to access the IO ports
* beyond the 0x3ff range: to get the full 65536 ports bitmapped
diff --git a/arch/mips/kernel/ipc.c b/arch/mips/kernel/ipc.c
index a68a91c21..2e91b6755 100644
--- a/arch/mips/kernel/ipc.c
+++ b/arch/mips/kernel/ipc.c
@@ -8,6 +8,8 @@
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
#include <linux/sem.h>
#include <linux/msg.h>
#include <linux/shm.h>
@@ -22,56 +24,68 @@
*/
asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
{
- int version;
+ int version, ret;
+ lock_kernel();
version = call >> 16; /* hack for backward compatibility */
call &= 0xffff;
if (call <= SEMCTL)
switch (call) {
case SEMOP:
- return sys_semop (first, (struct sembuf *)ptr, second);
+ ret = sys_semop (first, (struct sembuf *)ptr, second);
+ goto out;
case SEMGET:
- return sys_semget (first, second, third);
+ ret = sys_semget (first, second, third);
+ goto out;
case SEMCTL: {
union semun fourth;
- int err;
+ ret = -EINVAL;
if (!ptr)
- return -EINVAL;
- if ((err = verify_area (VERIFY_READ, ptr, sizeof(long))))
- return err;
- get_user(fourth.__pad, (void **) ptr);
- return sys_semctl (first, second, third, fourth);
+ goto out;
+ ret = -EFAULT;
+ if (get_user(fourth.__pad, (void **) ptr))
+ goto out;
+ ret = sys_semctl (first, second, third, fourth);
+ goto out;
}
default:
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
if (call <= MSGCTL)
switch (call) {
case MSGSND:
- return sys_msgsnd (first, (struct msgbuf *) ptr,
- second, third);
+ ret = sys_msgsnd (first, (struct msgbuf *) ptr,
+ second, third);
+ goto out;
case MSGRCV:
switch (version) {
case 0: {
struct ipc_kludge tmp;
- int err;
+ ret = -EINVAL;
if (!ptr)
- return -EINVAL;
- if ((err = verify_area (VERIFY_READ, ptr, sizeof(tmp))))
- return err;
- copy_from_user(&tmp,(struct ipc_kludge *) ptr, sizeof (tmp));
- return sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
+ goto out;
+ ret = -EFAULT;
+ if (copy_from_user(&tmp,(struct ipc_kludge *) ptr,
+ sizeof (tmp)))
+ goto out;
+ ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
+ goto out;
}
case 1: default:
- return sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third);
+ ret = sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third);
+ goto out;
}
case MSGGET:
- return sys_msgget ((key_t) first, second);
+ ret = sys_msgget ((key_t) first, second);
+ goto out;
case MSGCTL:
- return sys_msgctl (first, second, (struct msqid_ds *) ptr);
+ ret = sys_msgctl (first, second, (struct msqid_ds *) ptr);
+ goto out;
default:
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
if (call <= SHMCTL)
switch (call) {
@@ -79,28 +93,35 @@ asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr,
switch (version) {
case 0: default: {
ulong raddr;
- int err;
- if ((err = verify_area(VERIFY_WRITE, (ulong*) third, sizeof(ulong))))
- return err;
- err = sys_shmat (first, (char *) ptr, second, &raddr);
- if (err)
- return err;
- put_user (raddr, (ulong *) third);
- return 0;
- }
+ ret = sys_shmat (first, (char *) ptr, second, &raddr);
+ if (ret)
+ goto out;
+ ret = put_user (raddr, (ulong *) third);
+ goto out;
+ }
case 1: /* iBCS2 emulator entry point */
+ ret = -EINVAL;
if (get_fs() != get_ds())
- return -EINVAL;
- return sys_shmat (first, (char *) ptr, second, (ulong *) third);
+ goto out;
+ ret = sys_shmat (first, (char *) ptr, second, (ulong *) third);
+ goto out;
}
case SHMDT:
- return sys_shmdt ((char *)ptr);
+ ret = sys_shmdt ((char *)ptr);
+ goto out;
case SHMGET:
- return sys_shmget (first, second, third);
+ ret = sys_shmget (first, second, third);
+ goto out;
case SHMCTL:
- return sys_shmctl (first, second, (struct shmid_ds *) ptr);
+ ret = sys_shmctl (first, second, (struct shmid_ds *) ptr);
+ goto out;
default:
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
- return -EINVAL;
+ else
+ ret = -EINVAL;
+out:
+ unlock_kernel();
+ return ret;
}
diff --git a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c
index ec4f5c449..46345b308 100644
--- a/arch/mips/kernel/irixelf.c
+++ b/arch/mips/kernel/irixelf.c
@@ -27,7 +27,7 @@
#include <linux/personality.h>
#include <linux/elfcore.h>
-#include <asm/segment.h>
+#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <linux/config.h>
@@ -47,7 +47,7 @@ static struct linux_binfmt irix_format = {
#ifndef MODULE
NULL, NULL, load_irix_binary, load_irix_library, irix_core_dump
#else
- NULL, &mod_use_count_, load_irix_binary, load_irix_library, irix_core_dump
+ NULL, &__this_module.usecount, load_irix_binary, load_irix_library, irix_core_dump
#endif
};
@@ -138,23 +138,11 @@ static void set_brk(unsigned long start, unsigned long end)
static void padzero(unsigned long elf_bss)
{
unsigned long nbyte;
- char * fpnt;
-
+
nbyte = elf_bss & (PAGE_SIZE-1);
if (nbyte) {
nbyte = PAGE_SIZE - nbyte;
- /* FIXME: someone should investigate, why a bad binary
- * is allowed to bring a wrong elf_bss until here,
- * and how to react. Suffice the plain return?
- * rossius@hrz.tu-chemnitz.de
- */
- if (verify_area(VERIFY_WRITE, (void *) elf_bss, nbyte))
- return;
-
- fpnt = (char *) elf_bss;
- do {
- put_user(0, fpnt++);
- } while (--nbyte);
+ clear_user((void *) elf_bss, nbyte);
}
}
@@ -163,9 +151,9 @@ unsigned long * create_irix_tables(char * p, int argc, int envc,
unsigned int interp_load_addr,
struct pt_regs *regs, struct elf_phdr *ephdr)
{
- unsigned long *argv,*envp, *dlinfo;
- unsigned long * sp;
- unsigned long * csp;
+ char **argv, **envp;
+ unsigned long *sp;
+ unsigned long *csp;
#ifdef DEBUG_ELF
printk("create_irix_tables: p[%p] argc[%d] envc[%d] "
@@ -183,52 +171,51 @@ unsigned long * create_irix_tables(char * p, int argc, int envc,
sp--;
sp -= exec ? DLINFO_ITEMS*2 : 2;
- dlinfo = sp;
sp -= envc+1;
- envp = sp;
+ envp = (char **) sp;
sp -= argc+1;
- argv = sp;
+ argv = (char **) sp;
- put_user((unsigned long)argc, --sp);
+ __put_user((unsigned long)argc, --sp);
-#define NEW_AUX_ENT(id, val) \
- put_user ((id), dlinfo++); \
- put_user ((val), dlinfo++)
+#define NEW_AUX_ENT(nr, id, val) \
+ __put_user ((id), sp+(nr*2)); \
+ __put_user ((val), sp+(nr*2+1)); \
#define INTERP_ALIGN (~((64 * 1024) - 1))
+ NEW_AUX_ENT (0, AT_NULL, 0);
if(exec) {
struct elf_phdr * eppnt;
eppnt = (struct elf_phdr *) exec->e_phoff;
/* Put this here for an ELF program interpreter */
- NEW_AUX_ENT (AT_PHDR, ephdr->p_vaddr);
- NEW_AUX_ENT (AT_PHENT, sizeof (struct elf_phdr));
- NEW_AUX_ENT (AT_PHNUM, exec->e_phnum);
- NEW_AUX_ENT (AT_PAGESZ, PAGE_SIZE);
- NEW_AUX_ENT (AT_BASE, (interp_load_addr & (INTERP_ALIGN)));
- NEW_AUX_ENT (AT_FLAGS, 0);
- NEW_AUX_ENT (AT_ENTRY, (unsigned long) exec->e_entry);
- NEW_AUX_ENT (AT_UID, (unsigned long) current->uid);
- NEW_AUX_ENT (AT_EUID, (unsigned long) current->euid);
- NEW_AUX_ENT (AT_GID, (unsigned long) current->gid);
- NEW_AUX_ENT (AT_EGID, (unsigned long) current->egid);
+ NEW_AUX_ENT (0, AT_PHDR, ephdr->p_vaddr);
+ NEW_AUX_ENT (1, AT_PHENT, sizeof (struct elf_phdr));
+ NEW_AUX_ENT (2, AT_PHNUM, exec->e_phnum);
+ NEW_AUX_ENT (3, AT_PAGESZ, PAGE_SIZE);
+ NEW_AUX_ENT (4, AT_BASE, (interp_load_addr & (INTERP_ALIGN)));
+ NEW_AUX_ENT (5, AT_FLAGS, 0);
+ NEW_AUX_ENT (6, AT_ENTRY, (unsigned long) exec->e_entry);
+ NEW_AUX_ENT (7, AT_UID, (unsigned long) current->uid);
+ NEW_AUX_ENT (8, AT_EUID, (unsigned long) current->euid);
+ NEW_AUX_ENT (9, AT_GID, (unsigned long) current->gid);
+ NEW_AUX_ENT (10, AT_EGID, (unsigned long) current->egid);
}
- NEW_AUX_ENT (AT_NULL, 0);
#undef NEW_AUX_ENT
current->mm->arg_start = (unsigned long) p;
while (argc-->0) {
- put_user(p,argv++);
- while (get_user(p++)) /* nothing */ ;
+ __put_user(p, argv++);
+ p += strlen_user(p);
}
- put_user(0,argv);
+ __put_user(NULL, argv);
current->mm->arg_end = current->mm->env_start = (unsigned long) p;
while (envc-->0) {
- put_user(p,envp++);
- while (get_user(p++)) /* nothing */ ;
+ __put_user(p, envp++);
+ p += strlen_user(p);
}
- put_user(0,envp);
+ __put_user(NULL, envp);
current->mm->env_end = (unsigned long) p;
return sp;
}
@@ -255,7 +242,7 @@ static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex,
int error;
int i;
unsigned int k;
-
+
elf_bss = 0;
last_bss = 0;
error = load_addr = 0;
@@ -265,22 +252,22 @@ static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex,
#endif
/* First of all, some simple consistency checks */
- if((interp_elf_ex->e_type != ET_EXEC &&
- interp_elf_ex->e_type != ET_DYN) ||
- INCOMPATIBLE_MACHINE(interp_elf_ex->e_machine) ||
+ if((interp_elf_ex->e_type != ET_EXEC &&
+ interp_elf_ex->e_type != ET_DYN) ||
+ !elf_check_arch(interp_elf_ex->e_machine) ||
(!interpreter_inode->i_op ||
!interpreter_inode->i_op->default_file_ops->mmap)){
printk("IRIX interp has bad e_type %d\n", interp_elf_ex->e_type);
return 0xffffffff;
}
-
+
/* Now read in all of the header information */
if(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > PAGE_SIZE) {
printk("IRIX interp header bigger than a page (%d)\n",
(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum));
return 0xffffffff;
}
-
+
elf_phdata = (struct elf_phdr *)
kmalloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum,
GFP_KERNEL);
@@ -289,7 +276,7 @@ static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex,
printk("Cannot kmalloc phdata for IRIX interp.\n");
return 0xffffffff;
}
-
+
/* If the size of this structure has changed, then punt, since
* we will be doing the wrong thing.
*/
@@ -303,7 +290,7 @@ static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex,
retval = read_exec(interpreter_inode, interp_elf_ex->e_phoff,
(char *) elf_phdata,
sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, 1);
-
+
#ifdef DEBUG_ELF
dump_phdrs(elf_phdata, interp_elf_ex->e_phnum);
#endif
@@ -328,7 +315,7 @@ static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex,
if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
elf_type |= MAP_FIXED;
vaddr = eppnt->p_vaddr;
-
+
#ifdef DEBUG_ELF
printk("INTERP do_mmap(%p, %08lx, %08lx, %08lx, %08lx, %08lx) ",
file, vaddr,
@@ -340,7 +327,7 @@ static unsigned int load_irix_interp(struct elfhdr * interp_elf_ex,
eppnt->p_filesz + (eppnt->p_vaddr & 0xfff),
elf_prot, elf_type,
eppnt->p_offset & 0xfffff000);
-
+
if(error < 0 && error > -1024) {
printk("Aieee IRIX interp mmap error=%d\n", error);
break; /* Real error */
@@ -416,15 +403,15 @@ static int verify_binary(struct elfhdr *ehp, struct linux_binprm *bprm)
if (ehp->e_ident[0] != 0x7f || strncmp(&ehp->e_ident[1], "ELF", 3)) {
return -ENOEXEC;
}
-
+
/* First of all, some simple consistency checks */
if((ehp->e_type != ET_EXEC && ehp->e_type != ET_DYN) ||
- INCOMPATIBLE_MACHINE(ehp->e_machine) ||
+ !elf_check_arch(ehp->e_machine) ||
(!bprm->inode->i_op || !bprm->inode->i_op->default_file_ops ||
!bprm->inode->i_op->default_file_ops->mmap)) {
return -ENOEXEC;
}
-
+
/* Only support MIPS ARCH2 or greater IRIX binaries for now. */
if(!(ehp->e_flags & EF_MIPS_ARCH) && !(ehp->e_flags & 0x04)) {
return -ENOEXEC;
@@ -824,8 +811,8 @@ static inline int do_load_irix_library(int fd)
return -EACCES;
/* Seek to the beginning of the file. */
- if (file->f_op->lseek) {
- if ((error = file->f_op->lseek(inode, file, 0, 0)) != 0)
+ if (file->f_op->llseek) {
+ if ((error = file->f_op->llseek(inode, file, 0, 0)) != 0)
return -ENOEXEC;
} else
file->f_pos = 0;
@@ -842,7 +829,7 @@ static inline int do_load_irix_library(int fd)
/* First of all, some simple consistency checks. */
if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
- INCOMPATIBLE_MACHINE(elf_ex.e_machine) ||
+ !elf_check_arch(elf_ex.e_machine) ||
(!inode->i_op || !inode->i_op->default_file_ops->mmap))
return -ENOEXEC;
@@ -990,8 +977,8 @@ static int dump_write(struct file *file, const void *addr, int nr)
static int dump_seek(struct file *file, off_t off)
{
- if (file->f_op->lseek) {
- if (file->f_op->lseek(file->f_inode, file, off, 0) != off)
+ if (file->f_op->llseek) {
+ if (file->f_op->llseek(file->f_inode, file, off, 0) != off)
return 0;
} else
file->f_pos = off;
@@ -1134,7 +1121,7 @@ static int irix_core_dump(long signr, struct pt_regs * regs)
memset(elf.e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD);
elf.e_type = ET_CORE;
- elf.e_machine = ELF_EM_CPU;
+ elf.e_machine = ELF_ARCH;
elf.e_version = EV_CURRENT;
elf.e_entry = 0;
elf.e_phoff = sizeof(elf);
@@ -1234,8 +1221,8 @@ static int irix_core_dump(long signr, struct pt_regs * regs)
len = current->mm->arg_end - current->mm->arg_start;
len = len >= ELF_PRARGSZ ? ELF_PRARGSZ : len;
- memcpy_fromfs(&psinfo.pr_psargs,
- (const char *)current->mm->arg_start, len);
+ copy_from_user(&psinfo.pr_psargs,
+ (const char *)current->mm->arg_start, len);
for(i = 0; i < len; i++)
if (psinfo.pr_psargs[i] == 0)
psinfo.pr_psargs[i] = ' ';
diff --git a/arch/mips/kernel/irixioctl.c b/arch/mips/kernel/irixioctl.c
index a8498084b..3405904fa 100644
--- a/arch/mips/kernel/irixioctl.c
+++ b/arch/mips/kernel/irixioctl.c
@@ -52,11 +52,11 @@ static struct tty_struct *get_real_tty(struct tty_struct *tp)
asmlinkage int irix_ioctl(int fd, unsigned long cmd, unsigned long arg)
{
- unsigned long *data;
struct tty_struct *tp, *rtp;
int error = 0;
int old_fs;
+ lock_kernel();
#ifdef DEBUG_IOCTLS
printk("[%s:%d] irix_ioctl(%d, ", current->comm, current->pid, fd);
#endif
@@ -250,5 +250,6 @@ asmlinkage int irix_ioctl(int fd, unsigned long cmd, unsigned long arg)
#ifdef DEBUG_IOCTLS
printk("error=%d\n", error);
#endif
+ unlock_kernel();
return error;
}
diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c
index 94f8004f6..6a5636c76 100644
--- a/arch/mips/kernel/irixsig.c
+++ b/arch/mips/kernel/irixsig.c
@@ -112,7 +112,8 @@ static void setup_irix_frame(struct sigaction * sa, struct pt_regs *regs,
regs->regs[25] = regs->cp0_epc = current->tss.irix_trampoline;
}
-extern asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
+asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,
+ int options, unsigned long *ru);
asmlinkage int do_irix_signal(unsigned long oldmask, struct pt_regs * regs)
{
@@ -150,7 +151,7 @@ asmlinkage int do_irix_signal(unsigned long oldmask, struct pt_regs * regs)
if (signr != SIGCHLD)
continue;
/* check for SIGCHLD: it's special */
- while (sys_waitpid(-1,NULL,WNOHANG) > 0)
+ while (sys_wait4(-1,NULL,WNOHANG, NULL) > 0)
/* nothing */;
continue;
}
@@ -198,7 +199,7 @@ asmlinkage int do_irix_signal(unsigned long oldmask, struct pt_regs * regs)
}
}
handler_signal |= 1 << (signr-1);
- mask &= ~*to_k_sigset_t(&sa->sa_mask);
+ mask &= ~sa->sa_mask;
}
/*
* Who's code doesn't conform to the restartable syscall convention
@@ -224,8 +225,8 @@ asmlinkage int do_irix_signal(unsigned long oldmask, struct pt_regs * regs)
setup_irix_frame(sa, regs, signr, oldmask);
if (sa->sa_flags & SA_ONESHOT)
sa->sa_handler = NULL;
- current->blocked |= *to_k_sigset_t(&sa->sa_mask);
- oldmask |= *to_k_sigset_t(&sa->sa_mask);
+ current->blocked |= sa->sa_mask;
+ oldmask |= sa->sa_mask;
}
return 1;
@@ -282,7 +283,11 @@ asmlinkage unsigned long irix_sigreturn(struct pt_regs *regs)
return res;
badframe:
+ lock_kernel();
do_exit(SIGSEGV);
+ unlock_kernel();
+
+ return res;
}
struct sigact_irix5 {
@@ -306,22 +311,22 @@ static inline void check_pending(int signum)
struct sigaction *p;
p = signum - 1 + current->sig->action;
+ spin_lock(&current->sigmask_lock);
if (p->sa_handler == SIG_IGN) {
current->signal &= ~_S(signum);
- return;
- }
- if (p->sa_handler == SIG_DFL) {
+ } else if if (p->sa_handler == SIG_DFL) {
if (signum != SIGCONT && signum != SIGCHLD && signum != SIGWINCH)
return;
current->signal &= ~_S(signum);
- return;
}
+ spin_unlock(&current->sigmask_lock);
}
asmlinkage int irix_sigaction(int sig, struct sigact_irix5 *new,
struct sigact_irix5 *old, unsigned long trampoline)
{
struct sigaction new_sa, *p;
+ int res;
#ifdef DEBUG_SIG
printk(" (%d,%s,%s,%08lx) ", sig, (!new ? "0" : "NEW"),
@@ -330,16 +335,18 @@ asmlinkage int irix_sigaction(int sig, struct sigact_irix5 *new,
dump_sigact_irix5(new); printk(" ");
}
#endif
- if(sig < 1 || sig > 32)
+ if(sig < 1 || sig > 32) {
return -EINVAL;
+ }
p = sig - 1 + current->sig->action;
if(new) {
- int err = verify_area(VERIFY_READ, new, sizeof(*new));
- if(err)
- return err;
- if(sig == SIGKILL || sig == SIGSTOP)
+ res = verify_area(VERIFY_READ, new, sizeof(*new));
+ if(res)
+ return res;
+ if(sig == SIGKILL || sig == SIGSTOP) {
return -EINVAL;
+ }
new_sa.sa_flags = new->flags;
new_sa.sa_handler = (__sighandler_t) new->handler;
new_sa.sa_mask.__sigbits[1] = new_sa.sa_mask.__sigbits[2] =
@@ -347,9 +354,9 @@ asmlinkage int irix_sigaction(int sig, struct sigact_irix5 *new,
new_sa.sa_mask.__sigbits[0] = new->sigset[0];
if(new_sa.sa_handler != SIG_DFL && new_sa.sa_handler != SIG_IGN) {
- err = verify_area(VERIFY_READ, new_sa.sa_handler, 1);
- if(err)
- return err;
+ res = verify_area(VERIFY_READ, new_sa.sa_handler, 1);
+ if(res)
+ return res;
}
}
/* Hmmm... methinks IRIX libc always passes a valid trampoline
@@ -358,9 +365,9 @@ asmlinkage int irix_sigaction(int sig, struct sigact_irix5 *new,
*/
current->tss.irix_trampoline = trampoline;
if(old) {
- int err = verify_area(VERIFY_WRITE, old, sizeof(*old));
- if(err)
- return err;
+ int res = verify_area(VERIFY_WRITE, old, sizeof(*old));
+ if(res)
+ return res;
old->flags = p->sa_flags;
old->handler = (void *) p->sa_handler;
old->sigset[1] = old->sigset[2] = old->sigset[3] = 0;
@@ -369,23 +376,30 @@ asmlinkage int irix_sigaction(int sig, struct sigact_irix5 *new,
}
if(new) {
+ spin_lock_irq(&current->sig->siglock);
*p = new_sa;
check_pending(sig);
+ spin_unlock_irq(&current->sig->siglock);
}
-
return 0;
}
asmlinkage int irix_sigpending(unsigned long *set)
{
- int err;
-
- err = verify_area(VERIFY_WRITE, set, (sizeof(unsigned long) * 4));
- if(!err) {
- set[1] = set[2] = set[3] = 0;
- set[0] = (current->blocked & current->signal);
+ int res;
+
+ lock_kernel();
+ res = verify_area(VERIFY_WRITE, set, (sizeof(unsigned long) * 4));
+ if(!res) {
+ /* fill in "set" with signals pending but blocked. */
+ spin_lock_irq(&current->sigmask_lock);
+ __put_user(0, &set[1]);
+ __put_user(0, &set[2]);
+ __put_user(0, &set[3]);
+ __put_user((current->blocked & current->signal), &set[0]);
+ spin_unlock_irq(&current->sigmask_lock);
}
- return err;
+ return res;
}
asmlinkage int irix_sigprocmask(int how, unsigned long *new, unsigned long *old)
@@ -420,9 +434,12 @@ asmlinkage int irix_sigprocmask(int how, unsigned long *new, unsigned long *old)
error = verify_area(VERIFY_WRITE, old, (sizeof(unsigned long) * 4));
if(error)
return error;
- old[1] = old[2] = old[3] = 0;
- old[0] = oldbits;
+ __put_user(0, &old[1]);
+ __put_user(0, &old[2]);
+ __put_user(0, &old[3]);
+ __put_user(oldbits, &old[0]);
}
+
return 0;
}
@@ -430,15 +447,16 @@ asmlinkage int irix_sigsuspend(struct pt_regs *regs)
{
unsigned int mask;
unsigned long *uset;
- int base = 0;
+ int base = 0, error;
if(regs->regs[2] == 1000)
base = 1;
- mask = current->blocked;
uset = (unsigned long *) regs->regs[base + 4];
if(verify_area(VERIFY_READ, uset, (sizeof(unsigned long) * 4)))
return -EFAULT;
+ mask = current->blocked;
+
current->blocked = uset[0] & _BLOCKABLE;
while(1) {
current->state = TASK_INTERRUPTIBLE;
@@ -446,6 +464,7 @@ asmlinkage int irix_sigsuspend(struct pt_regs *regs)
if(do_irix_signal(mask, regs))
return -EINTR;
}
+ return error;
}
/* hate hate hate... */
@@ -492,6 +511,7 @@ asmlinkage int irix_sigpoll_sys(unsigned long *set, struct irix5_siginfo *info,
unsigned long mask, kset, expire = 0;
int sig, error, timeo = 0;
+ lock_kernel();
#ifdef DEBUG_SIG
printk("[%s:%d] irix_sigpoll_sys(%p,%p,%p)\n",
current->comm, current->pid, set, info, tp);
@@ -500,25 +520,24 @@ asmlinkage int irix_sigpoll_sys(unsigned long *set, struct irix5_siginfo *info,
/* Must always specify the signal set. */
if(!set)
return -EINVAL;
- kset = set[0];
- error = verify_area(VERIFY_READ, set, (sizeof(unsigned long) * 4));
+ error = get_user(kset, &set[0]);
if(error)
- return error;
+ goto out;
- if(info) {
- error = verify_area(VERIFY_WRITE, info, sizeof(*info));
- if(error)
- return error;
- memset(info, 0, sizeof(*info));
+ if(info && clear_user(info, sizeof(*info))) {
+ error = -EFAULT;
+ goto out;
}
if(tp) {
error = verify_area(VERIFY_READ, tp, sizeof(*tp));
if(error)
return error;
- if(!tp->tv_sec && !tp->tv_nsec)
- return -EINVAL;
+ if(!tp->tv_sec && !tp->tv_nsec) {
+ error = -EINVAL;
+ goto out;
+ }
expire = timespectojiffies(tp)+(tp->tv_sec||tp->tv_nsec)+jiffies;
current->timeout = expire;
}
@@ -539,12 +558,17 @@ asmlinkage int irix_sigpoll_sys(unsigned long *set, struct irix5_siginfo *info,
if(mask & current->signal) {
/* XXX need more than this... */
if(info) info->sig = sig;
- return 0;
+ error = 0;
+ goto out;
}
}
/* Should not get here, but do something sane if we do. */
- return -EINTR;
+ error = -EINTR;
+
+out:
+ unlock_kernel();
+ return error;
}
/* This is here because of irix5_siginfo definition. */
@@ -570,20 +594,27 @@ asmlinkage int irix_waitsys(int type, int pid, struct irix5_siginfo *info,
struct wait_queue wait = { current, NULL };
struct task_struct *p;
- if(!info)
- return -EINVAL;
- flag = verify_area(VERIFY_WRITE, info, sizeof(*info));
- if(flag)
- return flag;
+ lock_kernel();
+ if(!info) {
+ retval = -EINVAL;
+ goto out;
+ }
+ retval = verify_area(VERIFY_WRITE, info, sizeof(*info));
+ if(retval)
+ goto out;
if(ru) {
- flag = verify_area(VERIFY_WRITE, ru, sizeof(*ru));
- if(flag)
- return flag;
+ retval = verify_area(VERIFY_WRITE, ru, sizeof(*ru));
+ if(retval)
+ goto out;
+ }
+ if(options & ~(W_MASK)) {
+ retval = -EINVAL;
+ goto out;
+ }
+ if(type != P_PID && type != P_PGID && type != P_ALL) {
+ retval = -EINVAL;
+ goto out;
}
- if(options & ~(W_MASK))
- return -EINVAL;
- if(type != P_PID && type != P_PGID && type != P_ALL)
- return -EINVAL;
add_wait_queue(&current->wait_chldexit, &wait);
repeat:
flag = 0;
@@ -604,15 +635,13 @@ repeat:
continue;
if (ru != NULL)
getrusage(p, RUSAGE_BOTH, ru);
- info->sig = SIGCHLD;
- info->code = 0;
- info->stuff.procinfo.pid = p->pid;
- info->stuff.procinfo.procdata.child.status =
- (p->exit_code >> 8) & 0xff;
- info->stuff.procinfo.procdata.child.utime =
- p->utime;
- info->stuff.procinfo.procdata.child.stime =
- p->stime;
+ __put_user(SIGCHLD, &info->sig);
+ __put_user(0, &info->code);
+ __put_user(p->pid, &info->stuff.procinfo.pid);
+ __put_user((p->exit_code >> 8) & 0xff,
+ &info->stuff.procinfo.procdata.child.status);
+ __put_user(p->utime, &info->stuff.procinfo.procdata.child.utime);
+ __put_user(p->stime, &info->stuff.procinfo.procdata.child.stime);
p->exit_code = 0;
retval = 0;
goto end_waitsys;
@@ -621,15 +650,15 @@ repeat:
current->cstime += p->stime + p->cstime;
if (ru != NULL)
getrusage(p, RUSAGE_BOTH, ru);
- info->sig = SIGCHLD;
- info->code = 1; /* CLD_EXITED */
- info->stuff.procinfo.pid = p->pid;
- info->stuff.procinfo.procdata.child.status =
- (p->exit_code >> 8) & 0xff;
- info->stuff.procinfo.procdata.child.utime =
- p->utime;
- info->stuff.procinfo.procdata.child.stime =
- p->stime;
+ __put_user(SIGCHLD, &info->sig);
+ __put_user(1, &info->code); /* CLD_EXITED */
+ __put_user(p->pid, &info->stuff.procinfo.pid);
+ __put_user((p->exit_code >> 8) & 0xff,
+ &info->stuff.procinfo.procdata.child.status);
+ __put_user(p->utime,
+ &info->stuff.procinfo.procdata.child.utime);
+ __put_user(p->stime,
+ &info->stuff.procinfo.procdata.child.stime);
retval = 0;
if (p->p_opptr != p->p_pptr) {
REMOVE_LINKS(p);
@@ -657,6 +686,9 @@ repeat:
retval = -ECHILD;
end_waitsys:
remove_wait_queue(&current->wait_chldexit, &wait);
+
+out:
+ unlock_kernel();
return retval;
}
@@ -678,6 +710,7 @@ asmlinkage int irix_getcontext(struct pt_regs *regs)
int error, i, base = 0;
struct irix5_context *ctx;
+ lock_kernel();
if(regs->regs[2] == 1000)
base = 1;
ctx = (struct irix5_context *) regs->regs[base + 4];
@@ -689,7 +722,7 @@ asmlinkage int irix_getcontext(struct pt_regs *regs)
error = verify_area(VERIFY_WRITE, ctx, sizeof(*ctx));
if(error)
- return error;
+ goto out;
ctx->flags = 0x0f;
ctx->link = current->tss.irix_oldctx;
ctx->sigmask[1] = ctx->sigmask[2] = ctx->sigmask[4] = 0;
@@ -712,7 +745,11 @@ asmlinkage int irix_getcontext(struct pt_regs *regs)
/* XXX wheee... */
printk("Wheee, no code for saving IRIX FPU context yet.\n");
}
- return 0;
+ error = 0;
+
+out:
+ unlock_kernel();
+ return error;
}
asmlinkage unsigned long irix_setcontext(struct pt_regs *regs)
@@ -720,6 +757,7 @@ asmlinkage unsigned long irix_setcontext(struct pt_regs *regs)
int error, base = 0;
struct irix5_context *ctx;
+ lock_kernel();
if(regs->regs[2] == 1000)
base = 1;
ctx = (struct irix5_context *) regs->regs[base + 4];
@@ -731,7 +769,7 @@ asmlinkage unsigned long irix_setcontext(struct pt_regs *regs)
error = verify_area(VERIFY_READ, ctx, sizeof(*ctx));
if(error)
- return error;
+ goto out;
if(ctx->flags & 0x02) {
/* XXX sigstack garbage, todo... */
@@ -754,7 +792,11 @@ asmlinkage unsigned long irix_setcontext(struct pt_regs *regs)
printk("Wheee, cannot restore FPU context yet...\n");
}
current->tss.irix_oldctx = ctx->link;
- return regs->regs[2];
+ error = regs->regs[2];
+
+out:
+ unlock_kernel();
+ return error;
}
struct irix_sigstack { unsigned long sp; int status; };
@@ -763,6 +805,7 @@ asmlinkage int irix_sigstack(struct irix_sigstack *new, struct irix_sigstack *ol
{
int error;
+ lock_kernel();
#ifdef DEBUG_SIG
printk("[%s:%d] irix_sigstack(%p,%p)\n",
current->comm, current->pid, new, old);
@@ -770,15 +813,18 @@ asmlinkage int irix_sigstack(struct irix_sigstack *new, struct irix_sigstack *ol
if(new) {
error = verify_area(VERIFY_READ, new, sizeof(*new));
if(error)
- return error;
+ goto out;
}
if(old) {
error = verify_area(VERIFY_WRITE, old, sizeof(*old));
if(error)
- return error;
+ goto out;
}
- return 0;
+ error = 0;
+out:
+ unlock_kernel();
+ return error;
}
struct irix_sigaltstack { unsigned long sp; int size; int status; };
@@ -788,6 +834,7 @@ asmlinkage int irix_sigaltstack(struct irix_sigaltstack *new,
{
int error;
+ lock_kernel();
#ifdef DEBUG_SIG
printk("[%s:%d] irix_sigaltstack(%p,%p)\n",
current->comm, current->pid, new, old);
@@ -795,15 +842,19 @@ asmlinkage int irix_sigaltstack(struct irix_sigaltstack *new,
if(new) {
error = verify_area(VERIFY_READ, new, sizeof(*new));
if(error)
- return error;
+ goto out;
}
if(old) {
error = verify_area(VERIFY_WRITE, old, sizeof(*old));
if(error)
- return error;
+ goto out;
}
- return 0;
+ error = 0;
+
+out:
+ error = 0;
+ unlock_kernel();
}
struct irix_procset {
@@ -814,7 +865,10 @@ asmlinkage int irix_sigsendset(struct irix_procset *pset, int sig)
{
int error;
+ lock_kernel();
error = verify_area(VERIFY_READ, pset, sizeof(*pset));
+ if(error)
+ goto out;
#ifdef DEBUG_SIG
printk("[%s:%d] irix_sigsendset([%d,%d,%d,%d,%d],%d)\n",
current->comm, current->pid,
@@ -822,5 +876,9 @@ asmlinkage int irix_sigsendset(struct irix_procset *pset, int sig)
sig);
#endif
- return -EINVAL;
+ error = -EINVAL;
+
+out:
+ unlock_kernel();
+ return error;
}
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
index 2192112e9..a78bc3417 100644
--- a/arch/mips/kernel/irq.c
+++ b/arch/mips/kernel/irq.c
@@ -38,6 +38,7 @@
unsigned char cache_21 = 0xff;
unsigned char cache_A1 = 0xff;
+unsigned int local_irq_count[NR_CPUS];
unsigned long spurious_count = 0;
/*
@@ -99,11 +100,11 @@ extern void interrupt(void);
extern void fast_interrupt(void);
extern void bad_interrupt(void);
-static struct irqaction *irq_action[16] = {
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL
+static struct irqaction *irq_action[32] = {
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
};
int get_irq_list(char *buf)
@@ -111,7 +112,7 @@ int get_irq_list(char *buf)
int i, len = 0;
struct irqaction * action;
- for (i = 0 ; i < 16 ; i++) {
+ for (i = 0 ; i < 32 ; i++) {
action = irq_action[i];
if (!action)
continue;
@@ -129,6 +130,15 @@ int get_irq_list(char *buf)
return len;
}
+atomic_t __mips_bh_counter;
+
+#ifdef __SMP__
+#error Send superfluous SMP boxes to ralf@uni-koblenz.de
+#else
+#define irq_enter(cpu, irq) (++local_irq_count[cpu])
+#define irq_exit(cpu, irq) (--local_irq_count[cpu])
+#endif
+
/*
* do_IRQ handles IRQ's that have been installed without the
* SA_INTERRUPT flag: it uses the full signal-handling return
@@ -139,18 +149,28 @@ int get_irq_list(char *buf)
asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
{
struct irqaction * action = *(irq + irq_action);
+ int do_random, cpu = smp_processor_id();
+
+ irq_enter(cpu, irq);
kstat.interrupts[irq]++;
+
#ifdef CONFIG_SGI
prom_printf("Got irq %d, press a key.", irq);
prom_getchar();
romvec->imode();
#endif
+ /* slow interrupts run with interrupts enabled */
+ sti();
+ action = *(irq + irq_action);
+ do_random = 0;
while (action) {
- if (action->flags & SA_SAMPLE_RANDOM)
- add_interrupt_randomness(irq);
+ do_random |= action->flags;
action->handler(irq, action->dev_id, regs);
action = action->next;
}
+ if (do_random & SA_SAMPLE_RANDOM)
+ add_interrupt_randomness(irq);
+ irq_exit(cpu, irq);
}
/*
@@ -160,15 +180,21 @@ asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
*/
asmlinkage void do_fast_IRQ(int irq)
{
- struct irqaction * action = *(irq + irq_action);
+ struct irqaction * action;
+ int do_random, cpu = smp_processor_id();
+ irq_enter(cpu, irq);
kstat.interrupts[irq]++;
- while (action) {
- if (action->flags & SA_SAMPLE_RANDOM)
- add_interrupt_randomness(irq);
+ action = *(irq + irq_action);
+ do_random = 0;
+ while (action) {
+ do_random |= action->flags;
action->handler(irq, action->dev_id, NULL);
action = action->next;
- }
+ }
+ if (do_random & SA_SAMPLE_RANDOM)
+ add_interrupt_randomness(irq);
+ irq_exit(cpu, irq);
}
/*
@@ -228,7 +254,7 @@ int request_irq(unsigned int irq,
int retval;
struct irqaction * action;
- if (irq > 15)
+ if (irq > 31)
return -EINVAL;
if (!handler)
return -EINVAL;
@@ -256,7 +282,7 @@ void free_irq(unsigned int irq, void *dev_id)
struct irqaction * action, **p;
unsigned long flags;
- if (irq > 15) {
+ if (irq > 31) {
printk("Trying to free IRQ%d\n",irq);
return;
}
@@ -284,7 +310,7 @@ unsigned long probe_irq_on (void)
unsigned int i, irqs = 0, irqmask;
unsigned long delay;
- /* first, enable any unassigned irqs */
+ /* first, enable any unassigned (E)ISA irqs */
for (i = 15; i > 0; i--) {
if (!irq_action[i]) {
enable_irq(i);
@@ -322,7 +348,7 @@ void init_IRQ(void)
{
int i;
- for (i = 0; i < 16 ; i++)
+ for (i = 0; i < 32 ; i++)
set_int_vector(i, bad_interrupt);
irq_setup();
}
diff --git a/arch/mips/kernel/ksyms.c b/arch/mips/kernel/ksyms.c
deleted file mode 100644
index 28650741e..000000000
--- a/arch/mips/kernel/ksyms.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Export MIPS-specific functions needed for loadable modules.
- *
- * 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) 1996 by Ralf Baechle
- */
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <asm/dma.h>
-#include <asm/floppy.h>
-#include <asm/io.h>
-
-static struct symbol_table arch_symbol_table = {
-#include <linux/symtab_begin.h>
- X(EISA_bus),
- /*
- * String functions
- */
- X(memset),
- X(memcpy),
- X(memmove),
- X(bcopy),
- /*
- * Functions to control caches.
- */
- X(fd_cacheflush),
- /*
- * Base address of ports for Intel style I/O.
- */
- X(port_base),
-#include <linux/symtab_end.h>
-};
-
-void arch_syms_export(void)
-{
- register_symtab(&arch_symbol_table);
-}
diff --git a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c
new file mode 100644
index 000000000..abcb1946e
--- /dev/null
+++ b/arch/mips/kernel/mips_ksyms.c
@@ -0,0 +1,44 @@
+/*
+ * Export MIPS-specific functions needed for loadable modules.
+ *
+ * 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) 1996 by Ralf Baechle
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <asm/dma.h>
+#include <asm/floppy.h>
+#include <asm/io.h>
+#include <asm/softirq.h>
+
+EXPORT_SYMBOL(EISA_bus);
+
+/*
+ * String functions
+ */
+EXPORT_SYMBOL_NOVERS(memset);
+EXPORT_SYMBOL_NOVERS(memcpy);
+EXPORT_SYMBOL_NOVERS(memmove);
+EXPORT_SYMBOL_NOVERS(bcopy);
+
+EXPORT_SYMBOL(__mips_bh_counter);
+EXPORT_SYMBOL(local_irq_count);
+
+/* Networking helper routines. */
+EXPORT_SYMBOL(csum_partial_copy);
+
+/*
+ * Functions to control caches.
+ */
+EXPORT_SYMBOL(fd_cacheflush);
+
+/*
+ * Base address of ports for Intel style I/O.
+ */
+EXPORT_SYMBOL(port_base);
diff --git a/arch/mips/kernel/pci.c b/arch/mips/kernel/pci.c
new file mode 100644
index 000000000..e521ecdd9
--- /dev/null
+++ b/arch/mips/kernel/pci.c
@@ -0,0 +1,177 @@
+/*
+ * 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.
+ *
+ * MIPS implementation of PCI BIOS services for PCI support.
+ */
+#include <linux/bios32.h>
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <asm/pci.h>
+
+#ifndef CONFIG_PCI
+
+/*
+ * BIOS32 replacement.
+ */
+unsigned long pcibios_init(unsigned long memory_start, unsigned long memory_end)
+{
+ return memory_start;
+}
+
+#else /* defined(CONFIG_PCI) */
+
+/*
+ * Following the generic parts of the MIPS BIOS32 code.
+ */
+
+int pcibios_present (void)
+{
+ return _pcibios_init != NULL;
+}
+
+/*
+ * Given the vendor and device ids, find the n'th instance of that device
+ * in the system.
+ */
+int pcibios_find_device (unsigned short vendor, unsigned short device_id,
+ unsigned short index, unsigned char *bus,
+ unsigned char *devfn)
+{
+ unsigned int curr = 0;
+ struct pci_dev *dev;
+
+ for (dev = pci_devices; dev; dev = dev->next) {
+ if (dev->vendor == vendor && dev->device == device_id) {
+ if (curr == index) {
+ *devfn = dev->devfn;
+ *bus = dev->bus->number;
+ return PCIBIOS_SUCCESSFUL;
+ }
+ ++curr;
+ }
+ }
+ return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+/*
+ * Given the class, find the n'th instance of that device
+ * in the system.
+ */
+int pcibios_find_class (unsigned int class_code, unsigned short index,
+ unsigned char *bus, unsigned char *devfn)
+{
+ unsigned int curr = 0;
+ struct pci_dev *dev;
+
+ for (dev = pci_devices; dev; dev = dev->next) {
+ if (dev->class == class_code) {
+ if (curr == index) {
+ *devfn = dev->devfn;
+ *bus = dev->bus->number;
+ return PCIBIOS_SUCCESSFUL;
+ }
+ ++curr;
+ }
+ }
+ return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+const char *pcibios_strerror (int error)
+{
+ static char buf[80];
+
+ switch (error) {
+ case PCIBIOS_SUCCESSFUL:
+ return "SUCCESSFUL";
+
+ case PCIBIOS_FUNC_NOT_SUPPORTED:
+ return "FUNC_NOT_SUPPORTED";
+
+ case PCIBIOS_BAD_VENDOR_ID:
+ return "SUCCESSFUL";
+
+ case PCIBIOS_DEVICE_NOT_FOUND:
+ return "DEVICE_NOT_FOUND";
+
+ case PCIBIOS_BAD_REGISTER_NUMBER:
+ return "BAD_REGISTER_NUMBER";
+
+ default:
+ sprintf (buf, "UNKNOWN RETURN 0x%x", error);
+ return buf;
+ }
+}
+
+/*
+ * The functions below are machine specific and must be reimplented for
+ * each PCI chipset configuration. We just run the hook to the machine
+ * specific implementation.
+ */
+unsigned long (*_pcibios_init)(unsigned long memory_start, unsigned long memory_end);
+unsigned long pcibios_init(unsigned long memory_start, unsigned long memory_end)
+{
+ return _pcibios_init ? _pcibios_init(memory_start, memory_end)
+ : memory_start;
+}
+
+unsigned long (*_pcibios_fixup) (unsigned long memory_start,
+ unsigned long memory_end);
+unsigned long pcibios_fixup (unsigned long memory_start,
+ unsigned long memory_end)
+{
+ return _pcibios_fixup(memory_start, memory_end);
+}
+
+int (*_pcibios_read_config_byte) (unsigned char bus, unsigned char dev_fn,
+ unsigned char where, unsigned char *val);
+int pcibios_read_config_byte (unsigned char bus, unsigned char dev_fn,
+ unsigned char where, unsigned char *val)
+{
+ return _pcibios_read_config_byte(bus, dev_fn, where, val);
+}
+
+int (*_pcibios_read_config_word) (unsigned char bus, unsigned char dev_fn,
+ unsigned char where, unsigned short *val);
+int pcibios_read_config_word (unsigned char bus, unsigned char dev_fn,
+ unsigned char where, unsigned short *val)
+{
+ return _pcibios_read_config_word(bus, dev_fn, where, val);
+}
+
+int (*_pcibios_read_config_dword) (unsigned char bus, unsigned char dev_fn,
+ unsigned char where, unsigned int *val);
+int pcibios_read_config_dword (unsigned char bus, unsigned char dev_fn,
+ unsigned char where, unsigned int *val)
+{
+ return _pcibios_read_config_dword(bus, dev_fn, where, val);
+}
+
+int (*_pcibios_write_config_byte) (unsigned char bus, unsigned char dev_fn,
+ unsigned char where, unsigned char val);
+int pcibios_write_config_byte (unsigned char bus, unsigned char dev_fn,
+ unsigned char where, unsigned char val)
+{
+ return _pcibios_write_config_byte(bus, dev_fn, where, val);
+}
+
+int (*_pcibios_write_config_word) (unsigned char bus, unsigned char dev_fn,
+ unsigned char where, unsigned short val);
+int pcibios_write_config_word (unsigned char bus, unsigned char dev_fn,
+ unsigned char where, unsigned short val)
+{
+ return _pcibios_write_config_word(bus, dev_fn, where, val);
+}
+
+int (*_pcibios_write_config_dword) (unsigned char bus, unsigned char dev_fn,
+ unsigned char where, unsigned int val);
+int pcibios_write_config_dword (unsigned char bus, unsigned char dev_fn,
+ unsigned char where, unsigned int val)
+{
+ return _pcibios_write_config_dword(bus, dev_fn, where, val);
+}
+
+#endif /* defined(CONFIG_PCI) */
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 99e3a3075..f8b10bdea 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -24,7 +24,6 @@
#include <linux/a.out.h>
#include <asm/bootinfo.h>
-#include <asm/segment.h>
#include <asm/pgtable.h>
#include <asm/system.h>
#include <asm/mipsregs.h>
@@ -65,7 +64,7 @@ void release_thread(struct task_struct *dead_task)
{
}
-void copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
+int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
struct task_struct * p, struct pt_regs * regs)
{
struct pt_regs * childregs;
@@ -106,6 +105,8 @@ void copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
~(ST0_CU3|ST0_CU2|ST0_CU1|ST0_KSU|ST0_ERL|ST0_EXL);
childregs->cp0_status &= ~(ST0_CU3|ST0_CU2|ST0_CU1);
p->mm->context = 0;
+
+ return 0;
}
/* Fill in the fpu structure for a core dump.. */
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 018b68023..41deb8f18 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -9,6 +9,8 @@
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
#include <linux/user.h>
#include <asm/uaccess.h>
@@ -255,7 +257,9 @@ static int write_long(struct task_struct * tsk, unsigned long addr,
asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
{
struct task_struct *child;
+ int res;
+ lock_kernel();
#if 0
printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n",
(int) request, (int) pid, (unsigned long) addr,
@@ -263,30 +267,43 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
#endif
if (request == PTRACE_TRACEME) {
/* are we already being traced? */
- if (current->flags & PF_PTRACED)
- return -EPERM;
+ if (current->flags & PF_PTRACED) {
+ res = -EPERM;
+ goto out;
+ }
/* set the ptrace bit in the process flags. */
current->flags |= PF_PTRACED;
- return 0;
+ res = 0;
+ goto out;
+ }
+ if (pid == 1) { /* you may not mess with init */
+ res = -EPERM;
+ goto out;
+ }
+ if (!(child = get_task(pid))) {
+ res = -ESRCH;
+ goto out;
}
- if (pid == 1) /* you may not mess with init */
- return -EPERM;
- if (!(child = get_task(pid)))
- return -ESRCH;
if (request == PTRACE_ATTACH) {
- if (child == current)
- return -EPERM;
+ if (child == current) {
+ res = -EPERM;
+ goto out;
+ }
if ((!child->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->suid) ||
(current->uid != child->uid) ||
(current->gid != child->egid) ||
(current->gid != child->sgid) ||
- (current->gid != child->gid)) && !suser())
- return -EPERM;
+ (current->gid != child->gid)) && !suser()) {
+ res = -EPERM;
+ goto out;
+ }
/* the same process cannot be attached many times */
- if (child->flags & PF_PTRACED)
- return -EPERM;
+ if (child->flags & PF_PTRACED) {
+ res = -EPERM;
+ goto out;
+ }
child->flags |= PF_PTRACED;
if (child->p_pptr != current) {
REMOVE_LINKS(child);
@@ -294,31 +311,35 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
SET_LINKS(child);
}
send_sig(SIGSTOP, child, 1);
- return 0;
+ res = 0;
+ goto out;
+ }
+ if (!(child->flags & PF_PTRACED)) {
+ res = -ESRCH;
+ goto out;
}
- if (!(child->flags & PF_PTRACED))
- return -ESRCH;
if (child->state != TASK_STOPPED) {
- if (request != PTRACE_KILL)
- return -ESRCH;
+ if (request != PTRACE_KILL) {
+ res = -ESRCH;
+ goto out;
+ }
+ }
+ if (child->p_pptr != current) {
+ res = -ESRCH;
+ goto out;
}
- if (child->p_pptr != current)
- return -ESRCH;
switch (request) {
/* when I and D space are separate, these will need to be fixed. */
case PTRACE_PEEKTEXT: /* read word at location addr. */
case PTRACE_PEEKDATA: {
unsigned long tmp;
- int res;
res = read_long(child, addr, &tmp);
if (res < 0)
- return res;
- res = verify_area(VERIFY_WRITE, (void *) data, sizeof(long));
- if (!res)
- put_user(tmp,(unsigned long *) data);
- return res;
+ goto out;
+ res = put_user(tmp,(unsigned long *) data);
+ goto out;
}
/* read the word at location addr in the USER area. */
@@ -326,14 +347,10 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
case PTRACE_PEEKUSR: {
struct pt_regs *regs;
unsigned long tmp;
- int res;
regs = (struct pt_regs *)
(child->tss.ksp - sizeof(struct pt_regs));
- res = verify_area(VERIFY_WRITE, (void *) data, sizeof(long));
- if(res < 0)
- return res;
- res = tmp = 0; /* Default return value. */
+ tmp = 0; /* Default return value. */
if(addr < 32 && addr >= 0) {
tmp = regs->regs[addr];
} else if(addr >= 32 && addr < 64) {
@@ -370,18 +387,18 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
default:
tmp = 0;
res = -EIO;
- break;
+ goto out;
};
}
- if(!res)
- put_user(tmp, (unsigned long *) data);
- return res;
+ res = put_user(tmp, (unsigned long *) data);
+ goto out;
}
/* when I and D space are separate, this will have to be fixed. */
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA:
- return write_long(child,addr,data);
+ res = write_long(child,addr,data);
+ goto out;
case PTRACE_POKEUSR: {
struct pt_regs *regs;
@@ -419,20 +436,23 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
break;
};
}
- return res;
+ goto out;
}
case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
case PTRACE_CONT: { /* restart after signal. */
- if ((unsigned long) data > NSIG)
- return -EIO;
+ if ((unsigned long) data > NSIG) {
+ res = -EIO;
+ goto out;
+ }
if (request == PTRACE_SYSCALL)
child->flags |= PF_TRACESYS;
else
child->flags &= ~PF_TRACESYS;
child->exit_code = data;
wake_up_process(child);
- return data;
+ res = data;
+ goto out;
}
/*
@@ -445,24 +465,32 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
wake_up_process(child);
child->exit_code = SIGKILL;
}
- return 0;
+ res = 0;
+ goto out;
}
case PTRACE_DETACH: { /* detach a process that was attached. */
- if ((unsigned long) data > NSIG)
- return -EIO;
+ if ((unsigned long) data > NSIG) {
+ res = -EIO;
+ goto out;
+ }
child->flags &= ~(PF_PTRACED|PF_TRACESYS);
wake_up_process(child);
child->exit_code = data;
REMOVE_LINKS(child);
child->p_pptr = child->p_opptr;
SET_LINKS(child);
- return 0;
+ res = 0;
+ goto out;
}
default:
- return -EIO;
+ res = -EIO;
+ goto out;
}
+out:
+ unlock_kernel();
+ return res;
}
asmlinkage void syscall_trace(void)
@@ -479,7 +507,10 @@ asmlinkage void syscall_trace(void)
* for normal use. strace only continues with a signal if the
* stopping signal is not SIGTRAP. -brl
*/
- if (current->exit_code)
+ if (current->exit_code) {
+ spin_lock_irq(&current->sigmask_lock);
current->signal |= (1 << (current->exit_code - 1));
+ spin_unlock_irq(&current->sigmask_lock);
+ }
current->exit_code = 0;
}
diff --git a/arch/mips/kernel/r2300_fpu.S b/arch/mips/kernel/r2300_fpu.S
index 666a9a180..04a66df4e 100644
--- a/arch/mips/kernel/r2300_fpu.S
+++ b/arch/mips/kernel/r2300_fpu.S
@@ -16,7 +16,6 @@
#include <asm/regdef.h>
#include <asm/sigcontext.h>
- .text
.set mips3
.set noreorder
/* Save floating point context */
diff --git a/arch/mips/kernel/r2300_misc.S b/arch/mips/kernel/r2300_misc.S
index 0afdab4c9..1a557d456 100644
--- a/arch/mips/kernel/r2300_misc.S
+++ b/arch/mips/kernel/r2300_misc.S
@@ -18,7 +18,6 @@
#include <asm/pgtable.h>
#include <asm/processor.h>
#include <asm/regdef.h>
-#include <asm/segment.h>
#include <asm/stackframe.h>
.text
diff --git a/arch/mips/kernel/r2300_scall.S b/arch/mips/kernel/r2300_scall.S
index 358f46664..690a5c7c4 100644
--- a/arch/mips/kernel/r2300_scall.S
+++ b/arch/mips/kernel/r2300_scall.S
@@ -16,7 +16,6 @@
#include <asm/pgtable.h>
#include <asm/processor.h>
#include <asm/regdef.h>
-#include <asm/segment.h>
#include <asm/stackframe.h>
/*
@@ -29,7 +28,6 @@
* a2 (int) number of arguments to syscall
*/
.set noreorder
- .text
NESTED(r2300_do_syscalls, 32, sp)
subu sp,32
sw ra,28(sp)
@@ -83,4 +81,4 @@ dst: PTR 0b, 1b, 2b, 3b, 4b, 5b, 6b, 7b
PTR 7b,bad_stack
PTR 6b,bad_stack
PTR 5b,bad_stack
- .text
+ .previous
diff --git a/arch/mips/kernel/r2300_switch.S b/arch/mips/kernel/r2300_switch.S
index db03636d1..83190514b 100644
--- a/arch/mips/kernel/r2300_switch.S
+++ b/arch/mips/kernel/r2300_switch.S
@@ -16,7 +16,6 @@
#include <asm/pgtable.h>
#include <asm/processor.h>
#include <asm/regdef.h>
-#include <asm/segment.h>
#include <asm/stackframe.h>
#include <asm/asmmacro.h>
diff --git a/arch/mips/kernel/r4k_misc.S b/arch/mips/kernel/r4k_misc.S
index 510f513aa..432c65215 100644
--- a/arch/mips/kernel/r4k_misc.S
+++ b/arch/mips/kernel/r4k_misc.S
@@ -17,7 +17,6 @@
#include <asm/pgtable.h>
#include <asm/processor.h>
#include <asm/regdef.h>
-#include <asm/segment.h>
#include <asm/stackframe.h>
#define NOTLB_OPTIMIZE /* If you are paranoid, define this. */
@@ -105,7 +104,6 @@
_PAGE_VALID | _PAGE_DIRTY); \
sw pte, (ptr);
- .text
.set noreorder
.set mips3
diff --git a/arch/mips/kernel/r4k_scall.S b/arch/mips/kernel/r4k_scall.S
index d4dd88732..121616a50 100644
--- a/arch/mips/kernel/r4k_scall.S
+++ b/arch/mips/kernel/r4k_scall.S
@@ -16,10 +16,8 @@
#include <asm/pgtable.h>
#include <asm/processor.h>
#include <asm/regdef.h>
-#include <asm/segment.h>
#include <asm/stackframe.h>
- .text
.set noreorder
.set mips3
.align 5
@@ -71,4 +69,4 @@ dst: PTR 0b, 1b, 2b, 3b, 4b, 5b, 6b, 7b
PTR 7b,bad_stack
PTR 6b,bad_stack
PTR 5b,bad_stack
- .text
+ .previous
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index 22cd96fce..78ced5659 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -16,12 +16,10 @@
#include <asm/pgtable.h>
#include <asm/processor.h>
#include <asm/regdef.h>
-#include <asm/segment.h>
#include <asm/stackframe.h>
#include <asm/asmmacro.h>
- .text
.set noreorder
.set mips3
.align 5
diff --git a/arch/mips/kernel/reset.c b/arch/mips/kernel/reset.c
new file mode 100644
index 000000000..143449aac
--- /dev/null
+++ b/arch/mips/kernel/reset.c
@@ -0,0 +1,30 @@
+/*
+ * linux/arch/mips/sni/process.c
+ *
+ * Reset the machine.
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/reboot.h>
+#include <asm/reboot.h>
+
+/*
+ * Urgs ... Too many MIPS machines to handle this in a generic way.
+ * So handle all using function pointers to machine specific
+ * functions.
+ */
+
+void machine_restart(char *command)
+{
+ _machine_restart(command);
+}
+
+void machine_halt(void)
+{
+ _machine_halt();
+}
+
+void machine_power_off(void)
+{
+ _machine_power_off();
+}
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 48de5d21a..2e2b074f9 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -23,13 +23,16 @@
#ifdef CONFIG_BLK_DEV_RAM
#include <linux/blk.h>
#endif
+#ifdef CONFIG_RTC
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#endif
#include <asm/asm.h>
#include <asm/bootinfo.h>
#include <asm/cachectl.h>
#include <asm/io.h>
#include <asm/vector.h>
-#include <asm/segment.h>
#include <asm/stackframe.h>
#include <asm/system.h>
#ifdef CONFIG_SGI
@@ -63,11 +66,6 @@ char wait_available;
int EISA_bus = 0;
/*
- * Do a hardware reset.
- */
-void (*hard_reset_now)(void);
-
-/*
* 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
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index fdbc86558..848f0742b 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -7,6 +7,8 @@
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/errno.h>
@@ -23,77 +25,37 @@
#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
-asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
+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);
extern asmlinkage void (*save_fp_context)(struct sigcontext *sc);
extern asmlinkage void (*restore_fp_context)(struct sigcontext *sc);
-asmlinkage int sys_sigprocmask(int how, sigset_t *set, sigset_t *oset)
-{
- k_sigset_t new_set, old_set = current->blocked;
- int error;
-
- if (set) {
- error = verify_area(VERIFY_READ, set, sizeof(sigset_t));
- if (error)
- return error;
- new_set = *to_k_sigset_t(set) & _BLOCKABLE;
- switch (how) {
- case SIG_BLOCK:
- current->blocked |= new_set;
- break;
- case SIG_UNBLOCK:
- current->blocked &= ~new_set;
- break;
- case SIG_SETMASK:
- current->blocked = new_set;
- break;
- /*
- * SGI goodie: Just set the low 32 bits of 'blocked' even
- * for 128 bit sigset_t.
- */
- case SIG_SETMASK32:
- current->blocked = new_set;
- break;
- default:
- return -EINVAL;
- }
- }
- if (oset) {
- error = verify_area(VERIFY_WRITE, oset, sizeof(sigset_t));
- if (error)
- return error;
- put_user(old_set, &oset->__sigbits[0]);
- put_user(0, &oset->__sigbits[1]);
- put_user(0, &oset->__sigbits[2]);
- put_user(0, &oset->__sigbits[3]);
- }
- return 0;
-}
-
/*
* Atomically swap in the new signal mask, and wait for a signal.
+ * Unlike on Intel we pass a sigset_t *, not sigset_t.
*/
asmlinkage int sys_sigsuspend(struct pt_regs *regs)
{
- unsigned int mask;
- sigset_t *uset;
- k_sigset_t kset;
+ unsigned long mask;
+ sigset_t *uset, set;
- mask = current->blocked;
uset = (sigset_t *)(long) regs->regs[4];
- if (verify_area(VERIFY_READ, uset, sizeof(sigset_t)))
+ if (get_user(set, uset))
return -EFAULT;
- kset = *to_k_sigset_t(uset);
- current->blocked = kset & _BLOCKABLE;
+
+ spin_lock_irq(&current->sigmask_lock);
+ mask = current->blocked;
+ current->blocked = set & _BLOCKABLE;
+ spin_unlock_irq(&current->sigmask_lock);
+
regs->regs[2] = -EINTR;
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
- if (do_signal(mask,regs))
+ if (do_signal(mask, regs))
return -EINTR;
}
-
return -EINTR;
}
@@ -102,17 +64,12 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
struct sigcontext *context;
int i;
- /*
- * We don't support fixing ADEL/ADES exceptions for signal stack frames.
- * No big loss - who doesn't care about the alignment of this stack
- * really deserves to loose.
- */
context = (struct sigcontext *)(long) regs->regs[29];
if (!access_ok(VERIFY_READ, context, sizeof(struct sigcontext)) ||
(regs->regs[29] & (SZREG - 1)))
goto badframe;
- current->blocked = context->sc_sigset.__sigbits[0] & _BLOCKABLE;
+ current->blocked = context->sc_sigset & _BLOCKABLE;
regs->cp0_epc = context->sc_pc;
/*
@@ -140,7 +97,7 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
/*
* Don't let your children do this ...
*/
- asm __volatile__(
+ __asm__ __volatile__(
"move\t$29,%0\n\t"
"j\tret_from_sys_call"
:/* no outputs */
@@ -148,7 +105,9 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
/* Unreached */
badframe:
+ lock_kernel();
do_exit(SIGSEGV);
+ unlock_kernel();
}
/*
@@ -201,7 +160,7 @@ static void setup_frame(struct sigaction * sa, struct pt_regs *regs,
/* We realign the stack to an adequate boundary for the architecture. */
if (verify_area(VERIFY_WRITE, frame, sizeof (struct sc)))
- do_exit(SIGSEGV);
+ goto segv_and_exit;
frame = (struct sc *)((unsigned long)frame & ALMASK);
sc = &frame->scc;
@@ -235,10 +194,10 @@ static void setup_frame(struct sigaction * sa, struct pt_regs *regs,
__put_user(regs->lo, &sc->sc_mdlo);
__put_user(regs->cp0_cause, &sc->sc_cause);
__put_user((regs->cp0_status & ST0_CU1) != 0, &sc->sc_ownedfp);
- __put_user(oldmask, &sc->sc_sigset.__sigbits[0]);
- __put_user(0, &sc->sc_sigset.__sigbits[1]);
- __put_user(0, &sc->sc_sigset.__sigbits[2]);
- __put_user(0, &sc->sc_sigset.__sigbits[3]);
+ __put_user(oldmask, &sc->sc_sigset);
+ __put_user(0, &sc->__pad0[0]);
+ __put_user(0, &sc->__pad0[1]);
+ __put_user(0, &sc->__pad0[2]);
regs->regs[4] = signr; /* Arguments for handler */
regs->regs[5] = 0; /* For now. */
@@ -247,6 +206,11 @@ static void setup_frame(struct sigaction * sa, struct pt_regs *regs,
regs->regs[31] = (unsigned long) frame->code; /* Return address */
regs->cp0_epc = (unsigned long) sa->sa_handler; /* "return" to the first handler */
regs->regs[25] = regs->cp0_epc; /* PIC shit... */
+
+segv_and_exit:
+ lock_kernel();
+ do_exit(SIGSEGV);
+ unlock_kernel();
}
static inline void handle_signal(unsigned long signr, struct sigaction *sa,
@@ -256,9 +220,11 @@ static inline void handle_signal(unsigned long signr, struct sigaction *sa,
if (sa->sa_flags & SA_ONESHOT)
sa->sa_handler = NULL;
- if (!(sa->sa_flags & SA_NOMASK))
- current->blocked |=
- ((*to_k_sigset_t(&sa->sa_mask) | _S(signr)) & _BLOCKABLE);
+ if (!(sa->sa_flags & SA_NOMASK)) {
+ spin_lock_irq(&current->sigmask_lock);
+ current->blocked |= (sa->sa_mask | _S(signr)) & _BLOCKABLE;
+ spin_unlock_irq(&current->sigmask_lock);
+ }
}
static inline void syscall_restart(unsigned long r0, unsigned long or2,
@@ -319,7 +285,9 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
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);
continue;
}
sa = current->sig->action + signr - 1;
@@ -328,7 +296,7 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
if (signr != SIGCHLD)
continue;
/* check for SIGCHLD: it's special */
- while (sys_waitpid(-1,NULL,WNOHANG) > 0)
+ while (sys_wait4(-1,NULL,WNOHANG, NULL) > 0)
/* nothing */;
continue;
}
@@ -350,7 +318,6 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
schedule();
continue;
- case SIGQUIT: case SIGILL: case SIGTRAP:
case SIGIOT: case SIGFPE: case SIGSEGV: case SIGBUS:
if (current->binfmt && current->binfmt->core_dump) {
if (current->binfmt->core_dump(signr, regs))
@@ -358,25 +325,23 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
}
/* fall through */
default:
+ spin_lock_irq(&current->sigmask_lock);
current->signal |= _S(signr & 0x7f);
+ spin_unlock_irq(&current->sigmask_lock);
+
current->flags |= PF_SIGNALED;
+
+ lock_kernel(); /* 8-( */
do_exit(signr);
+ unlock_kernel();
}
}
/*
* OK, we're invoking a handler
*/
-#if 0
- printk("[%s:%d] send sig1: r0[%08lx] r7[%08lx] reg[2]=%08lx\n",
- current->comm, current->pid, r0, r7, regs->regs[2]);
-#endif
if(r0)
syscall_restart(r0, regs->orig_reg2,
r7, regs, sa);
-#if 0
- printk("send sig2: r0[%08lx] r7[%08lx] reg[2]=%08lx\n",
- r0, r7, regs->regs[2]);
-#endif
handle_signal(signr, sa, oldmask, regs);
return 1;
}
@@ -385,10 +350,6 @@ asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
* dies here!!! The li instruction, a single machine instruction,
* must directly be followed by the syscall instruction.
*/
-#if 0
- printk("[%s:%d] send sig3: r0[%08lx] r7[%08lx] reg[2]=%08lx\n",
- current->comm, current->pid, r0, r7, regs->regs[2]);
-#endif
if (r0 &&
(regs->regs[2] == ERESTARTNOHAND ||
regs->regs[2] == ERESTARTSYS ||
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index 3b595e05d..2faf604c7 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -17,6 +17,8 @@
#include <linux/config.h>
#include <linux/linkage.h>
#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
#include <linux/mman.h>
#include <linux/sched.h>
#include <linux/unistd.h>
@@ -35,35 +37,49 @@ extern unsigned char sys_narg_table[];
asmlinkage int sys_pipe(struct pt_regs *regs)
{
int fd[2];
- int error;
+ int error, res;
+ lock_kernel();
error = do_pipe(fd);
- if (error)
- return error;
+ if (error) {
+ res = error;
+ goto out;
+ }
regs->regs[3] = fd[1];
- return fd[0];
+ res = fd[0];
+out:
+ unlock_kernel();
+ return res;
}
asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len, int prot,
int flags, int fd, off_t offset)
{
struct file * file = NULL;
+ unsigned long res;
+ lock_kernel();
if (!(flags & MAP_ANONYMOUS)) {
if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
return -EBADF;
}
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
- return do_mmap(file, addr, len, prot, flags, offset);
+ res = do_mmap(file, addr, len, prot, flags, offset);
+
+ unlock_kernel();
+ return res;
}
asmlinkage int sys_idle(void)
{
- if (current->pid != 0)
- return -EPERM;
+ int ret = -EPERM;
+ lock_kernel();
+ if (current->pid != 0)
+ goto out;
/* endless idle loop with no priority at all */
+ current->priority = -100;
current->counter = -100;
for (;;) {
/*
@@ -76,25 +92,38 @@ asmlinkage int sys_idle(void)
__asm__(".set\tmips3\n\t"
"wait\n\t"
".set\tmips0\n\t");
+ run_task_queue(&tq_scheduler);
schedule();
}
+out:
+ unlock_kernel();
+ return ret;
}
asmlinkage int sys_fork(struct pt_regs *regs)
{
- return do_fork(SIGCHLD, regs->regs[29], regs);
+ int res;
+
+ lock_kernel();
+ res = do_fork(SIGCHLD, regs->regs[29], regs);
+ unlock_kernel();
+ return res;
}
asmlinkage int sys_clone(struct pt_regs *regs)
{
unsigned long clone_flags;
unsigned long newsp;
+ int res;
+ lock_kernel();
clone_flags = regs->regs[4];
newsp = regs->regs[5];
if (!newsp)
newsp = regs->regs[29];
- return do_fork(clone_flags, newsp, regs);
+ res = do_fork(clone_flags, newsp, regs);
+ unlock_kernel();
+ return res;
}
/*
@@ -102,20 +131,25 @@ asmlinkage int sys_clone(struct pt_regs *regs)
*/
asmlinkage int sys_execve(struct pt_regs *regs)
{
- int error;
+ int res;
char * filename;
- error = getname((char *) (long)regs->regs[4], &filename);
- if (error)
- return error;
- error = do_execve(filename, (char **) (long)regs->regs[5],
- (char **) (long)regs->regs[6], regs);
+ lock_kernel();
+ res = getname((char *) (long)regs->regs[4], &filename);
+ if (res)
+ goto out;
+ res = do_execve(filename, (char **) (long)regs->regs[5],
+ (char **) (long)regs->regs[6], regs);
putname(filename);
- return error;
+
+out:
+ unlock_kernel();
+ return res;
}
/*
* Do the indirect syscall syscall.
+ * Don't care about kernel locking; the actual syscall will do it.
*/
asmlinkage int sys_syscall(struct pt_regs *regs)
{
@@ -184,6 +218,7 @@ asmlinkage int sys_syscall(struct pt_regs *regs)
/*
* If we ever come here the user sp is bad. Zap the process right away.
* Due to the bad stack signaling wouldn't work.
+ * XXX kernel locking???
*/
asmlinkage void bad_stack(void)
{
@@ -204,6 +239,9 @@ static char *irix_sys_names[] = {
};
#endif
+/*
+ * This isn't entirely correct with respect to kernel locking ...
+ */
void do_sys(struct pt_regs *regs)
{
unsigned long syscallnr, usp;
diff --git a/arch/mips/kernel/syscalls.h b/arch/mips/kernel/syscalls.h
index 723cb5e34..4cf778acb 100644
--- a/arch/mips/kernel/syscalls.h
+++ b/arch/mips/kernel/syscalls.h
@@ -201,3 +201,8 @@ SYS(sys_setsockopt, 5)
SYS(sys_shutdown, 2)
SYS(sys_socket, 3)
SYS(sys_socketpair, 4)
+SYS(sys_setresuid, 3) /* 4185 */
+SYS(sys_getresuid, 3)
+SYS(sys_query_module, 5)
+SYS(sys_poll, 3)
+SYS(sys_nfsservctl, 3)
diff --git a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c
index c54f83595..9a4ddca3f 100644
--- a/arch/mips/kernel/sysirix.c
+++ b/arch/mips/kernel/sysirix.c
@@ -54,12 +54,13 @@ asmlinkage int irix_sysmp(struct pt_regs *regs)
int base = 0;
int error = 0;
+ lock_kernel();
if(regs->regs[2] == 1000)
base = 1;
cmd = regs->regs[base + 4];
switch(cmd) {
case MP_PGSIZE:
- return PAGE_SIZE;
+ error = PAGE_SIZE;
break;
default:
@@ -69,6 +70,8 @@ asmlinkage int irix_sysmp(struct pt_regs *regs)
break;
}
+out:
+ unlock_kernel();
return error;
}
@@ -95,6 +98,7 @@ asmlinkage int irix_prctl(struct pt_regs *regs)
unsigned long cmd;
int error = 0, base = 0;
+ lock_kernel();
if(regs->regs[2] == 1000)
base = 1;
cmd = regs->regs[base + 4];
@@ -102,7 +106,8 @@ asmlinkage int irix_prctl(struct pt_regs *regs)
case PR_MAXPROCS:
printk("irix_prctl[%s:%d]: Wants PR_MAXPROCS\n",
current->comm, current->pid);
- return NR_TASKS;
+ error = NR_TASKS;
+ break;
case PR_ISBLOCKED: {
struct task_struct *task;
@@ -110,11 +115,14 @@ asmlinkage int irix_prctl(struct pt_regs *regs)
printk("irix_prctl[%s:%d]: Wants PR_ISBLOCKED\n",
current->comm, current->pid);
task = find_process_by_pid(regs->regs[base + 5]);
- if(!task)
- return -ESRCH;
- return (task->next_run ? 0 : 1);
+ if(!task) {
+ error = -ESRCH;
+ break;
+ }
+ error = (task->next_run ? 0 : 1);
/* Can _your_ OS find this out that fast? */
- }
+ break;
+ }
case PR_SETSTACKSIZE: {
long value = regs->regs[base + 5];
@@ -126,28 +134,35 @@ asmlinkage int irix_prctl(struct pt_regs *regs)
if(suser()) {
current->rlim[RLIMIT_STACK].rlim_max =
current->rlim[RLIMIT_STACK].rlim_cur = value;
- return value;
+ error = value;
+ break;
+ }
+ if(value > current->rlim[RLIMIT_STACK].rlim_max) {
+ error = -EINVAL;
+ break;
}
- if(value > current->rlim[RLIMIT_STACK].rlim_max)
- return -EINVAL;
current->rlim[RLIMIT_STACK].rlim_cur = value;
- return value;
+ error = value;
+ break;
}
case PR_GETSTACKSIZE:
printk("irix_prctl[%s:%d]: Wants PR_GETSTACKSIZE\n",
current->comm, current->pid);
- return current->rlim[RLIMIT_STACK].rlim_cur;
+ error = current->rlim[RLIMIT_STACK].rlim_cur;
+ break;
case PR_MAXPPROCS:
printk("irix_prctl[%s:%d]: Wants PR_MAXPROCS\n",
current->comm, current->pid);
- return 1;
+ error = 1;
+ break;
case PR_UNBLKONEXEC:
printk("irix_prctl[%s:%d]: Wants PR_UNBLKONEXEC\n",
current->comm, current->pid);
- return -EINVAL;
+ error = -EINVAL;
+ break;
case PR_SETEXITSIG:
printk("irix_prctl[%s:%d]: Wants PR_SETEXITSIG\n",
@@ -157,45 +172,54 @@ asmlinkage int irix_prctl(struct pt_regs *regs)
* exit_code to some non-zero value when this is requested,
* and check whether exit_code is already set in do_exit().
*/
- return -EINVAL;
+ error = -EINVAL;
+ break;
case PR_RESIDENT:
printk("irix_prctl[%s:%d]: Wants PR_RESIDENT\n",
current->comm, current->pid);
- return 0; /* Compatability indeed. */
+ error = 0; /* Compatability indeed. */
+ break;
case PR_ATTACHADDR:
printk("irix_prctl[%s:%d]: Wants PR_ATTACHADDR\n",
current->comm, current->pid);
- return -EINVAL;
+ error = -EINVAL;
+ break;
case PR_DETACHADDR:
printk("irix_prctl[%s:%d]: Wants PR_DETACHADDR\n",
current->comm, current->pid);
- return -EINVAL;
+ error = -EINVAL;
+ break;
case PR_TERMCHILD:
printk("irix_prctl[%s:%d]: Wants PR_TERMCHILD\n",
current->comm, current->pid);
- return -EINVAL;
+ error = -EINVAL;
+ break;
case PR_GETSHMASK:
printk("irix_prctl[%s:%d]: Wants PR_GETSHMASK\n",
current->comm, current->pid);
- return -EINVAL; /* Until I have the sproc() stuff in. */
+ error = -EINVAL; /* Until I have the sproc() stuff in. */
+ break;
case PR_GETNSHARE:
- return 0; /* Until I have the sproc() stuff in. */
+ error = 0; /* Until I have the sproc() stuff in. */
+ break;
case PR_COREPID:
printk("irix_prctl[%s:%d]: Wants PR_COREPID\n",
current->comm, current->pid);
- return -EINVAL;
+ error = -EINVAL;
+ break;
case PR_ATTACHADDRPERM:
printk("irix_prctl[%s:%d]: Wants PR_ATTACHADDRPERM\n",
current->comm, current->pid);
- return -EINVAL;
+ error = -EINVAL;
+ break;
case PR_PTHREADEXIT:
printk("irix_prctl[%s:%d]: Wants PR_PTHREADEXIT\n",
@@ -209,6 +233,8 @@ asmlinkage int irix_prctl(struct pt_regs *regs)
break;
}
+out:
+ unlock_kernel();
return error;
}
@@ -242,6 +268,7 @@ asmlinkage int irix_syssgi(struct pt_regs *regs)
unsigned long cmd;
int retval, base = 0;
+ lock_kernel();
if(regs->regs[2] == 1000)
base = 1;
@@ -251,7 +278,8 @@ asmlinkage int irix_syssgi(struct pt_regs *regs)
char *buf = (char *) regs->regs[base + 5];
/* XXX Use ethernet addr.... */
- return clear_user(buf, 64);
+ retval = clear_user(buf, 64);
+ break;
}
case SGI_RDNAME: {
@@ -261,77 +289,89 @@ asmlinkage int irix_syssgi(struct pt_regs *regs)
retval = verify_area(VERIFY_WRITE, buf, 16);
if(retval)
- return retval;
+ break;
for_each_task(p) {
if(p->pid == pid)
goto found0;
}
- return -ESRCH;
+ retval = -ESRCH;
found0:
copy_to_user(buf, p->comm, 16);
- return 0;
+ retval = 0;
}
case SGI_SETPGID: {
- int error;
-
#ifdef DEBUG_PROCGRPS
printk("[%s:%d] setpgid(%d, %d) ",
current->comm, current->pid,
(int) regs->regs[base + 5], (int)regs->regs[base + 6]);
#endif
- error = sys_setpgid(regs->regs[base + 5], regs->regs[base + 6]);
+ retval = sys_setpgid(regs->regs[base + 5], regs->regs[base + 6]);
#ifdef DEBUG_PROCGRPS
- printk("error=%d\n", error);
+ printk("retval=%d\n", retval);
#endif
- return error;
}
case SGI_SYSCONF: {
switch(regs->regs[base + 5]) {
case 1:
- return (MAX_ARG_PAGES >> 4); /* XXX estimate... */
+ retval = (MAX_ARG_PAGES >> 4); /* XXX estimate... */
+ goto out;
case 2:
- return NR_TASKS;
+ retval = NR_TASKS;
+ goto out;
case 3:
- return HZ;
+ retval = HZ;
+ goto out;
case 4:
- return NGROUPS;
+ retval = NGROUPS;
+ goto out;
case 5:
- return NR_OPEN;
+ retval = NR_OPEN;
+ goto out;
case 6:
- return 1;
+ retval = 1;
+ goto out;
case 7:
- return 1;
+ retval = 1;
+ goto out;
case 8:
- return 199009;
+ retval = 199009;
+ goto out;
case 11:
- return PAGE_SIZE;
+ retval = PAGE_SIZE;
+ goto out;
case 12:
- return 4;
+ retval = 4;
+ goto out;
case 25:
case 26:
case 27:
case 28:
case 29:
case 30:
- return 0;
+ retval = 0;
+ goto out;
case 31:
- return 32;
+ retval = 32;
+ goto out;
default:
- return -EINVAL;
+ retval = -EINVAL;
+ goto out;
};
}
case SGI_SETGROUPS:
- return sys_setgroups((int) regs->regs[base + 5],
- (gid_t *) regs->regs[base + 6]);
+ retval = sys_setgroups((int) regs->regs[base + 5],
+ (gid_t *) regs->regs[base + 6]);
+ break;
case SGI_GETGROUPS:
- return sys_getgroups((int) regs->regs[base + 5],
- (gid_t *) regs->regs[base + 6]);
+ retval = sys_getgroups((int) regs->regs[base + 5],
+ (gid_t *) regs->regs[base + 6]);
+ break;
case SGI_RUSAGE: {
struct rusage *ru = (struct rusage *) regs->regs[base + 6];
@@ -339,47 +379,50 @@ asmlinkage int irix_syssgi(struct pt_regs *regs)
switch((int) regs->regs[base + 5]) {
case 0:
/* rusage self */
- return getrusage(current, RUSAGE_SELF, ru);
+ retval = getrusage(current, RUSAGE_SELF, ru);
+ goto out;
case -1:
/* rusage children */
- return getrusage(current, RUSAGE_CHILDREN, ru);
+ retval = getrusage(current, RUSAGE_CHILDREN, ru);
+ goto out;
default:
- return -EINVAL;
+ retval = -EINVAL;
+ goto out;
};
}
case SGI_SSYNC:
sys_sync();
- return 0;
-
- case SGI_GETSID: {
- int error;
+ retval = 0;
+ break;
+ case SGI_GETSID:
#ifdef DEBUG_PROCGRPS
printk("[%s:%d] getsid(%d) ", current->comm, current->pid,
(int) regs->regs[base + 5]);
#endif
- error = sys_getsid(regs->regs[base + 5]);
+ retval = sys_getsid(regs->regs[base + 5]);
#ifdef DEBUG_PROCGRPS
- printk("error=%d\n", error);
+ printk("retval=%d\n", retval);
#endif
- return error;
- }
+ break;
case SGI_ELFMAP:
retval = irix_mapelf((int) regs->regs[base + 5],
(struct elf_phdr *) regs->regs[base + 6],
(int) regs->regs[base + 7]);
- return retval;
+ break;
case SGI_TOSSTSAVE:
/* XXX We don't need to do anything? */
- return 0;
+ retval = 0;
+ break;
case SGI_FP_BCOPY:
- return 0;
+ retval = 0;
+ break;
case SGI_PHYSP: {
pgd_t *pgdp;
@@ -400,13 +443,19 @@ asmlinkage int irix_syssgi(struct pt_regs *regs)
return 0;
}
}
- return -EINVAL;
+ retval = -EINVAL;
+ break;
}
default:
printk("irix_syssgi: Unsupported command %d\n", (int)cmd);
- return -EINVAL;
+ retval = -EINVAL;
+ break;
};
+
+out:
+ unlock_kernel();
+ return retval;
}
asmlinkage int irix_gtime(struct pt_regs *regs)
@@ -425,15 +474,20 @@ asmlinkage int irix_brk(unsigned long brk)
unsigned long rlim;
unsigned long newbrk, oldbrk;
struct mm_struct *mm = current->mm;
+ int ret;
- if (brk < current->mm->end_code)
- return -ENOMEM;
+ lock_kernel();
+ if (brk < current->mm->end_code) {
+ ret = -ENOMEM;
+ goto out;
+ }
newbrk = PAGE_ALIGN(brk);
oldbrk = PAGE_ALIGN(mm->brk);
if (oldbrk == newbrk) {
mm->brk = brk;
- return 0;
+ ret = 0;
+ goto out;
}
/*
@@ -442,7 +496,8 @@ asmlinkage int irix_brk(unsigned long brk)
if (brk <= current->mm->brk) {
mm->brk = brk;
do_munmap(newbrk, oldbrk-newbrk);
- return 0;
+ ret = 0;
+ goto out;
}
/*
* Check against rlimit and stack..
@@ -450,20 +505,26 @@ asmlinkage int irix_brk(unsigned long brk)
rlim = current->rlim[RLIMIT_DATA].rlim_cur;
if (rlim >= RLIM_INFINITY)
rlim = ~0;
- if (brk - mm->end_code > rlim)
- return -ENOMEM;
+ if (brk - mm->end_code > rlim) {
+ ret = -ENOMEM;
+ goto out;
+ }
/*
* Check against existing mmap mappings.
*/
- if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE))
+ if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE)) {
return -ENOMEM;
+ goto out;
+ }
/*
* Check if we have enough memory..
*/
- if (!vm_enough_memory((newbrk-oldbrk) >> PAGE_SHIFT))
+ if (!vm_enough_memory((newbrk-oldbrk) >> PAGE_SHIFT)) {
return -ENOMEM;
+ goto out;
+ }
/*
* Ok, looks good - let it rip.
@@ -473,7 +534,11 @@ asmlinkage int irix_brk(unsigned long brk)
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_FIXED|MAP_PRIVATE, 0);
- return 0;
+ ret = 0;
+
+out:
+ unlock_kernel();
+ return ret;
}
asmlinkage int irix_getpid(struct pt_regs *regs)
@@ -496,8 +561,13 @@ asmlinkage int irix_getgid(struct pt_regs *regs)
asmlinkage int irix_stime(int value)
{
- if(!suser())
- return -EPERM;
+ int ret;
+
+ lock_kernel();
+ if(!suser()) {
+ ret = -EPERM;
+ goto out;
+ }
cli();
xtime.tv_sec = value;
xtime.tv_usec = 0;
@@ -505,7 +575,11 @@ asmlinkage int irix_stime(int value)
time_maxerror = MAXPHASE;
time_esterror = MAXPHASE;
sti();
- return 0;
+ ret = 0;
+
+out:
+ unlock_kernel();
+ return ret;
}
extern int _setitimer(int which, struct itimerval *value, struct itimerval *ovalue);
@@ -541,6 +615,7 @@ asmlinkage unsigned int irix_alarm(unsigned int seconds)
struct itimerval it_new, it_old;
unsigned int oldalarm;
+ lock_kernel();
if(!seconds) {
getitimer_real(&it_old);
del_timer(&current->real_timer);
@@ -555,13 +630,16 @@ asmlinkage unsigned int irix_alarm(unsigned int seconds)
/* And we'd better return too much than too little anyway */
if (it_old.it_value.tv_usec)
oldalarm++;
+ unlock_kernel();
return oldalarm;
}
asmlinkage int irix_pause(void)
{
+ lock_kernel();
current->state = TASK_INTERRUPTIBLE;
schedule();
+ unlock_kernel();
return -EINTR;
}
@@ -572,11 +650,17 @@ extern asmlinkage int sys_mount(char * dev_name, char * dir_name, char * type,
asmlinkage int irix_mount(char *dev_name, char *dir_name, unsigned long flags,
char *type, void *data, int datalen)
{
+ int ret;
+
+ lock_kernel();
printk("[%s:%d] irix_mount(%p,%p,%08lx,%p,%p,%d)\n",
current->comm, current->pid,
dev_name, dir_name, flags, type, data, datalen);
- return sys_mount(dev_name, dir_name, type, flags, data);
- /* return -EINVAL; */
+ ret = sys_mount(dev_name, dir_name, type, flags, data);
+
+out:
+ unlock_kernel();
+ return ret;
}
struct irix_statfs {
@@ -593,17 +677,20 @@ asmlinkage int irix_statfs(const char *path, struct irix_statfs *buf,
int error, old_fs, i;
/* We don't support this feature yet. */
- if(fs_type)
- return -EINVAL;
+ if(fs_type) {
+ error = -EINVAL;
+ goto out;
+ }
error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statfs));
if (error)
- return error;
+ goto out;
error = namei(path,&inode);
if (error)
- return error;
+ goto out;
if (!inode->i_sb->s_op->statfs) {
iput(inode);
- return -ENOSYS;
+ error = -ENOSYS;
+ goto out;
}
old_fs = get_fs(); set_fs(get_ds());
@@ -622,8 +709,11 @@ asmlinkage int irix_statfs(const char *path, struct irix_statfs *buf,
__put_user(0, &buf->f_fname[i]);
__put_user(0, &buf->f_fpack[i]);
}
+ error = 0;
- return 0;
+out:
+ unlock_kernel();
+ return error;
}
asmlinkage int irix_fstatfs(unsigned int fd, struct irix_statfs *buf)
@@ -633,15 +723,22 @@ asmlinkage int irix_fstatfs(unsigned int fd, struct irix_statfs *buf)
struct file *file;
int error, old_fs, i;
+ lock_kernel();
error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statfs));
if (error)
- return error;
- if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
- return -EBADF;
- if (!(inode = file->f_inode))
- return -ENOENT;
- if (!inode->i_sb->s_op->statfs)
- return -ENOSYS;
+ goto out;
+ if (fd >= NR_OPEN || !(file = current->files->fd[fd])) {
+ error = -EBADF;
+ goto out;
+ }
+ if (!(inode = file->f_inode)) {
+ error = -ENOENT;
+ goto out;
+ }
+ if (!inode->i_sb->s_op->statfs) {
+ error = -ENOSYS;
+ goto out;
+ }
old_fs = get_fs(); set_fs(get_ds());
inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, sizeof(struct statfs));
@@ -658,8 +755,11 @@ asmlinkage int irix_fstatfs(unsigned int fd, struct irix_statfs *buf)
__put_user(0, &buf->f_fname[i]);
__put_user(0, &buf->f_fpack[i]);
}
+ error = 0;
- return 0;
+out:
+ unlock_kernel();
+ return error;
}
extern asmlinkage int sys_setpgid(pid_t pid, pid_t pgid);
@@ -669,6 +769,7 @@ asmlinkage int irix_setpgrp(int flags)
{
int error;
+ lock_kernel();
#ifdef DEBUG_PROCGRPS
printk("[%s:%d] setpgrp(%d) ", current->comm, current->pid, flags);
#endif
@@ -679,22 +780,29 @@ asmlinkage int irix_setpgrp(int flags)
#ifdef DEBUG_PROCGRPS
printk("returning %d\n", current->pgrp);
#endif
+
+out:
+ unlock_kernel();
return error;
}
asmlinkage int irix_times(struct tms * tbuf)
{
+ lock_kernel();
if (tbuf) {
int error = verify_area(VERIFY_WRITE,tbuf,sizeof *tbuf);
if (error)
- return error;
+ goto out;
__put_user(current->utime,&tbuf->tms_utime);
__put_user(current->stime,&tbuf->tms_stime);
__put_user(current->cutime,&tbuf->tms_cutime);
__put_user(current->cstime,&tbuf->tms_cstime);
}
+ error = 0;
- return 0;
+out:
+ unlock_kernel();
+ return error;
}
asmlinkage int irix_exec(struct pt_regs *regs)
@@ -702,14 +810,18 @@ asmlinkage int irix_exec(struct pt_regs *regs)
int error, base = 0;
char * filename;
+ lock_kernel();
if(regs->regs[2] == 1000)
base = 1;
error = getname((char *) (long)regs->regs[base + 4], &filename);
if (error)
- return error;
+ goto out;
error = do_execve(filename, (char **) (long)regs->regs[base + 5],
(char **) 0, regs);
putname(filename);
+
+out:
+ unlock_kernel();
return error;
}
@@ -718,14 +830,18 @@ asmlinkage int irix_exece(struct pt_regs *regs)
int error, base = 0;
char * filename;
+ lock_kernel();
if(regs->regs[2] == 1000)
base = 1;
error = getname((char *) (long)regs->regs[base + 4], &filename);
if (error)
- return error;
+ goto out;
error = do_execve(filename, (char **) (long)regs->regs[base + 5],
(char **) (long)regs->regs[base + 6], regs);
putname(filename);
+
+out:
+ unlock_kernel();
return error;
}
@@ -789,15 +905,20 @@ int irix_poll(struct poll * ufds, size_t nfds, int timeout)
select_table wait_table, *wait;
struct select_table_entry *entry;
+ lock_kernel();
if ((error = verify_area(VERIFY_READ, ufds, nfds*sizeof(struct poll))))
- return error;
+ goto out;
- if (nfds > NR_OPEN)
- return -EINVAL;
+ if (nfds > NR_OPEN) {
+ error = -EINVAL;
+ goto out;
+ }
if (!(entry = (struct select_table_entry*)__get_free_page(GFP_KERNEL))
- || !(fds = (struct poll *)kmalloc(nfds*sizeof(struct poll), GFP_KERNEL)))
- return -ENOMEM;
+ || !(fds = (struct poll *)kmalloc(nfds*sizeof(struct poll), GFP_KERNEL))) {
+ error = -ENOMEM;
+ goto out;
+ }
copy_from_user(fds, ufds, nfds*sizeof(struct poll));
@@ -854,8 +975,10 @@ repeat:
}
}
- if ((current->signal & (~current->blocked)))
- return -EINTR;
+ if ((current->signal & (~current->blocked))) {
+ error = -EINTR;
+ goto out;
+ }
wait = NULL;
if (!count && current->timeout > jiffies) {
@@ -878,20 +1001,28 @@ repeat:
kfree(fds1);
current->timeout = 0;
current->state = TASK_RUNNING;
- return fdcount;
+ error = fdcount;
+
+out:
+ unlock_kernel();
+ return error;
}
asmlinkage unsigned long irix_gethostid(void)
{
+ lock_kernel();
printk("[%s:%d]: irix_gethostid() called...\n",
current->comm, current->pid);
+ unlock_kernel();
return -EINVAL;
}
asmlinkage unsigned long irix_sethostid(unsigned long val)
{
+ lock_kernel();
printk("[%s:%d]: irix_sethostid(%08lx) called...\n",
current->comm, current->pid, val);
+ unlock_kernel();
return -EINVAL;
}
@@ -935,15 +1066,21 @@ asmlinkage int irix_getdomainname(char *name, int len)
{
int error;
+ lock_kernel();
if(len > (__NEW_UTS_LEN - 1))
len = __NEW_UTS_LEN - 1;
error = verify_area(VERIFY_WRITE, name, len);
if(error)
- return -EFAULT;
- if(copy_to_user(name, system_utsname.domainname, len))
- return -EFAULT;
+ goto out;
+ if(copy_to_user(name, system_utsname.domainname, len)) {
+ error = -EFAULT;
+ goto out;
+ }
+ error = 0;
- return 0;
+out:
+ unlock_kernel();
+ return error;
}
asmlinkage unsigned long irix_getpagesize(void)
@@ -1015,22 +1152,28 @@ asmlinkage int irix_lseek64(int fd, int _unused, int offhi, int offlow, int base
loff_t junk;
int old_fs, error;
+ lock_kernel();
old_fs = get_fs(); set_fs(get_ds());
error = sys_llseek(fd, offhi, offlow, &junk, base);
set_fs(old_fs);
if(error)
- return error;
- return (int) junk;
+ goto out;
+ error = (int) junk;
+out:
+ unlock_kernel();
+ return error;
}
asmlinkage int irix_sginap(int ticks)
{
+ lock_kernel();
if(ticks) {
current->timeout = ticks + jiffies;
current->state = TASK_INTERRUPTIBLE;
}
schedule();
+ unlock_kernel();
return 0;
}
@@ -1041,7 +1184,12 @@ asmlinkage int irix_sgikopt(char *istring, char *ostring, int len)
asmlinkage int irix_gettimeofday(struct timeval *tv)
{
- return copy_to_user(tv, &xtime, sizeof(*tv)) ? -EFAULT : 0;
+ int retval;
+
+ lock_kernel();
+ retval = copy_to_user(tv, &xtime, sizeof(*tv)) ? -EFAULT : 0;
+ unlock_kernel();
+ return retval;
}
asmlinkage unsigned long irix_mmap32(unsigned long addr, size_t len, int prot,
@@ -1050,34 +1198,46 @@ asmlinkage unsigned long irix_mmap32(unsigned long addr, size_t len, int prot,
struct file *file = NULL;
unsigned long retval;
+ lock_kernel();
if(!(flags & MAP_ANONYMOUS)) {
- if(fd >= NR_OPEN || !(file = current->files->fd[fd]))
- return -EBADF;
+ if(fd >= NR_OPEN || !(file = current->files->fd[fd])) {
+ retval = -EBADF;
+ goto out;
+ }
}
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
retval = do_mmap(file, addr, len, prot, flags, offset);
+
+out:
+ unlock_kernel();
return retval;
}
asmlinkage int irix_madvise(unsigned long addr, int len, int behavior)
{
+ lock_kernel();
printk("[%s:%d] Wheee.. irix_madvise(%08lx,%d,%d)\n",
current->comm, current->pid, addr, len, behavior);
+ unlock_kernel();
return -EINVAL;
}
asmlinkage int irix_pagelock(char *addr, int len, int op)
{
+ lock_kernel();
printk("[%s:%d] Wheee.. irix_pagelock(%p,%d,%d)\n",
current->comm, current->pid, addr, len, op);
+ unlock_kernel();
return -EINVAL;
}
asmlinkage int irix_quotactl(struct pt_regs *regs)
{
+ lock_kernel();
printk("[%s:%d] Wheee.. irix_quotactl()\n",
current->comm, current->pid);
+ unlock_kernel();
return -EINVAL;
}
@@ -1085,6 +1245,7 @@ asmlinkage int irix_BSDsetpgrp(int pid, int pgrp)
{
int error;
+ lock_kernel();
#ifdef DEBUG_PROCGRPS
printk("[%s:%d] BSDsetpgrp(%d, %d) ", current->comm, current->pid,
pid, pgrp);
@@ -1101,13 +1262,18 @@ asmlinkage int irix_BSDsetpgrp(int pid, int pgrp)
#ifdef DEBUG_PROCGRPS
printk("error = %d\n", error);
#endif
+
+out:
+ unlock_kernel();
return error;
}
asmlinkage int irix_systeminfo(int cmd, char *buf, int cnt)
{
+ lock_kernel();
printk("[%s:%d] Wheee.. irix_systeminfo(%d,%p,%d)\n",
current->comm, current->pid, cmd, buf, cnt);
+ unlock_kernel();
return -EINVAL;
}
@@ -1121,18 +1287,22 @@ struct iuname {
asmlinkage int irix_uname(struct iuname *buf)
{
- if(copy_to_user(system_utsname.sysname, buf->sysname, 65))
- return -EFAULT;
- if(copy_to_user(system_utsname.nodename, buf->nodename, 65))
- return -EFAULT;
- if(copy_to_user(system_utsname.release, buf->release, 65))
- return -EFAULT;
- if(copy_to_user(system_utsname.version, buf->version, 65))
- return -EFAULT;
- if(copy_to_user(system_utsname.machine, buf->machine, 65))
- return -EFAULT;
+ int retval;
+
+ lock_kernel();
+ if(copy_to_user(system_utsname.sysname, buf->sysname, 65)
+ || copy_to_user(system_utsname.nodename, buf->nodename, 65)
+ || copy_to_user(system_utsname.release, buf->release, 65)
+ || copy_to_user(system_utsname.version, buf->version, 65)
+ || copy_to_user(system_utsname.machine, buf->machine, 65)) {
+ retval = -EFAULT;
+ goto out;
+ }
+ retval = 1;
- return 1;
+out:
+ unlock_kernel();
+ return retval;
}
#undef DEBUG_XSTAT
@@ -1201,6 +1371,9 @@ extern asmlinkage int sys_newstat(char * filename, struct stat * statbuf);
asmlinkage int irix_xstat(int version, char *filename, struct stat *statbuf)
{
+ int retval;
+
+ lock_kernel();
#ifdef DEBUG_XSTAT
printk("[%s:%d] Wheee.. irix_xstat(%d,%s,%p) ",
current->comm, current->pid, version, filename, statbuf);
@@ -1208,41 +1381,50 @@ asmlinkage int irix_xstat(int version, char *filename, struct stat *statbuf)
switch(version) {
case 2: {
struct stat kb;
- int errno, old_fs;
+ int old_fs;
old_fs = get_fs(); set_fs(get_ds());
- errno = sys_newstat(filename, &kb);
+ retval = sys_newstat(filename, &kb);
set_fs(old_fs);
#ifdef DEBUG_XSTAT
- printk("errno[%d]\n", errno);
+ printk("retval[%d]\n", retval);
#endif
- if(errno)
- return errno;
- errno = irix_xstat32_xlate(&kb, statbuf);
- return errno;
+ if(retval)
+ goto out;
+ retval = irix_xstat32_xlate(&kb, statbuf);
+ goto out;
}
case 3: {
- int errno = sys_newstat(filename, statbuf);
+ retval = sys_newstat(filename, statbuf);
#ifdef DEBUG_XSTAT
- printk("errno[%d]\n", errno);
+ printk("retval[%d]\n", retval);
#endif
- if(errno)
- return errno;
+ if(retval)
+ goto out;
irix_xstat64_xlate(statbuf);
- return 0;
+ retval = 0;
+ break;
}
default:
- return -EINVAL;
+ retval = -EINVAL;
+ break;
}
+
+out:
+ unlock_kernel();
+ return retval;
}
extern asmlinkage int sys_newlstat(char * filename, struct stat * statbuf);
asmlinkage int irix_lxstat(int version, char *filename, struct stat *statbuf)
{
+ int error;
+
+ lock_kernel();
#ifdef DEBUG_XSTAT
printk("[%s:%d] Wheee.. irix_lxstat(%d,%s,%p) ",
current->comm, current->pid, version, filename, statbuf);
@@ -1250,41 +1432,50 @@ asmlinkage int irix_lxstat(int version, char *filename, struct stat *statbuf)
switch(version) {
case 2: {
struct stat kb;
- int errno, old_fs;
+ int old_fs;
old_fs = get_fs(); set_fs(get_ds());
- errno = sys_newlstat(filename, &kb);
+ error = sys_newlstat(filename, &kb);
set_fs(old_fs);
#ifdef DEBUG_XSTAT
- printk("errno[%d]\n", errno);
+ printk("error[%d]\n", error);
#endif
- if(errno)
- return errno;
- errno = irix_xstat32_xlate(&kb, statbuf);
- return errno;
+ if(error)
+ goto out;
+ error = irix_xstat32_xlate(&kb, statbuf);
+ goto error;
}
case 3: {
- int errno = sys_newlstat(filename, statbuf);
+ sys_newlstat(filename, statbuf);
#ifdef DEBUG_XSTAT
- printk("errno[%d]\n", errno);
+ printk("error[%d]\n", error);
#endif
- if(errno)
- return errno;
+ if(error)
+ goto out;
irix_xstat64_xlate(statbuf);
- return 0;
+ error = 0;
+ goto error;
}
default:
- return -EINVAL;
+ error = -EINVAL;
+ goto out;
}
+
+out:
+ unlock_kernel();
+ return errno;
}
extern asmlinkage int sys_newfstat(unsigned int fd, struct stat * statbuf);
asmlinkage int irix_fxstat(int version, int fd, struct stat *statbuf)
{
+ int error;
+
+ lock_kernel();
#ifdef DEBUG_XSTAT
printk("[%s:%d] Wheee.. irix_fxstat(%d,%d,%p) ",
current->comm, current->pid, version, fd, statbuf);
@@ -1292,56 +1483,73 @@ asmlinkage int irix_fxstat(int version, int fd, struct stat *statbuf)
switch(version) {
case 2: {
struct stat kb;
- int errno, old_fs;
+ int old_fs;
old_fs = get_fs(); set_fs(get_ds());
- errno = sys_newfstat(fd, &kb);
+ error = sys_newfstat(fd, &kb);
set_fs(old_fs);
#ifdef DEBUG_XSTAT
- printk("errno[%d]\n", errno);
+ printk("error[%d]\n", error);
#endif
- if(errno)
- return errno;
- errno = irix_xstat32_xlate(&kb, statbuf);
- return errno;
+ if(error)
+ goto out;
+ error = irix_xstat32_xlate(&kb, statbuf);
+ goto out;
}
case 3: {
- int errno = sys_newfstat(fd, statbuf);
+ error = sys_newfstat(fd, statbuf);
#ifdef DEBUG_XSTAT
- printk("errno[%d]\n", errno);
+ printk("error[%d]\n", error);
#endif
- if(errno)
- return errno;
+ if(error)
+ goto out;
irix_xstat64_xlate(statbuf);
- return 0;
+ error = 0;
+ goto out;
}
default:
- return -EINVAL;
+ error = -EINVAL;
+ goto out;
}
+
+out:
+ unlock_kernel();
+ return error;
}
extern asmlinkage int sys_mknod(const char * filename, int mode, dev_t dev);
asmlinkage int irix_xmknod(int ver, char *filename, int mode, dev_t dev)
{
+ int retval;
+
+ lock_kernel();
printk("[%s:%d] Wheee.. irix_xmknod(%d,%s,%x,%x)\n",
current->comm, current->pid, ver, filename, mode, (int) dev);
switch(ver) {
case 2:
- return sys_mknod(filename, mode, dev);
+ retval = sys_mknod(filename, mode, dev);
+ goto out;
default:
- return -EINVAL;
+ retval = -EINVAL;
+ goto out;
};
+
+out:
+ unlock_kernel();
+ return retval;
}
asmlinkage int irix_swapctl(int cmd, char *arg)
{
+ lock_kernel();
printk("[%s:%d] Wheee.. irix_swapctl(%d,%p)\n",
current->comm, current->pid, cmd, arg);
+ unlock_kernel();
return -EINVAL;
}
@@ -1359,17 +1567,19 @@ asmlinkage int irix_statvfs(char *fname, struct irix_statvfs *buf)
struct statfs kbuf;
int error, old_fs, i;
+ lock_kernel();
printk("[%s:%d] Wheee.. irix_statvfs(%s,%p)\n",
current->comm, current->pid, fname, buf);
error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
if(error)
- return error;
+ goto out;
error = namei(fname, &inode);
if(error)
- return error;
+ goto out;
if(!inode->i_sb->s_op->statfs) {
iput(inode);
- return -ENOSYS;
+ error = -ENOSYS;
+ goto out;
}
old_fs = get_fs(); set_fs(get_ds());
@@ -1397,7 +1607,11 @@ asmlinkage int irix_statvfs(char *fname, struct irix_statvfs *buf)
for(i = 0; i < 32; i++)
__put_user(0, &buf->f_fstr[i]);
- return 0;
+ error = 0;
+
+out:
+ unlock_kernel();
+ return error;
}
asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs *buf)
@@ -1407,18 +1621,25 @@ asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs *buf)
struct file *file;
int error, old_fs, i;
+ lock_kernel();
printk("[%s:%d] Wheee.. irix_fstatvfs(%d,%p)\n",
current->comm, current->pid, fd, buf);
error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
if (error)
- return error;
- if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
- return -EBADF;
- if (!(inode = file->f_inode))
- return -ENOENT;
- if (!inode->i_sb->s_op->statfs)
- return -ENOSYS;
+ goto out;
+ if (fd >= NR_OPEN || !(file = current->files->fd[fd])) {
+ error = -EBADF;
+ goto out;
+ }
+ if (!(inode = file->f_inode)) {
+ error = -ENOENT;
+ goto out;
+ }
+ if (!inode->i_sb->s_op->statfs) {
+ error = -ENOSYS;
+ goto out;
+ }
old_fs = get_fs(); set_fs(get_ds());
inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, sizeof(struct statfs));
@@ -1444,7 +1665,11 @@ asmlinkage int irix_fstatvfs(int fd, struct irix_statvfs *buf)
for(i = 0; i < 32; i++)
__put_user(0, &buf->f_fstr[i]);
- return 0;
+ error = 0;
+
+out:
+ unlock_kernel();
+ return error;
}
#define NOFOLLOW_LINKS 0
@@ -1511,27 +1736,41 @@ static inline int chown_common(char *filename, uid_t user, gid_t group, int foll
asmlinkage int irix_chown(char *fname, int uid, int gid)
{
+ int retval;
+
+ lock_kernel();
/* Do follow any and all links... */
- return chown_common(fname, uid, gid, FOLLOW_LINKS);
+ retval = chown_common(fname, uid, gid, FOLLOW_LINKS);
+ unlock_kernel();
+ return retval;
}
asmlinkage int irix_lchown(char *fname, int uid, int gid)
{
+ int retval;
+
+ lock_kernel();
/* Do _not_ follow any links... */
- return chown_common(fname, uid, gid, NOFOLLOW_LINKS);
+ retval = chown_common(fname, uid, gid, NOFOLLOW_LINKS);
+ unlock_kernel();
+ return retval;
}
asmlinkage int irix_priocntl(struct pt_regs *regs)
{
+ lock_kernel();
printk("[%s:%d] Wheee.. irix_priocntl()\n",
current->comm, current->pid);
+ unlock_kernel();
return -EINVAL;
}
asmlinkage int irix_sigqueue(int pid, int sig, int code, int val)
{
+ lock_kernel();
printk("[%s:%d] Wheee.. irix_sigqueue(%d,%d,%d,%d)\n",
current->comm, current->pid, pid, sig, code, val);
+ unlock_kernel();
return -EINVAL;
}
@@ -1540,16 +1779,34 @@ extern asmlinkage int sys_ftruncate(unsigned int fd, unsigned long length);
asmlinkage int irix_truncate64(char *name, int pad, int size1, int size2)
{
- if(size1)
- return -EINVAL;
- return sys_truncate(name, size2);
+ int retval;
+
+ lock_kernel();
+ if(size1) {
+ retval = -EINVAL;
+ goto out;
+ }
+ retval = sys_truncate(name, size2);
+
+out:
+ unlock_kernel();
+ return retval;
}
asmlinkage int irix_ftruncate64(int fd, int pad, int size1, int size2)
{
- if(size1)
- return -EINVAL;
- return sys_ftruncate(fd, size2);
+ int retval;
+
+ lock_kernel();
+ if(size1) {
+ retval = -EINVAL;
+ goto out;
+ }
+ retval = sys_ftruncate(fd, size2);
+
+out:
+ unlock_kernel();
+ return retval;
}
extern asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len, int prot,
@@ -1561,6 +1818,7 @@ asmlinkage int irix_mmap64(struct pt_regs *regs)
int len, prot, flags, fd, off1, off2, base = 0;
int error;
+ lock_kernel();
if(regs->regs[2] == 1000)
base = 1;
sp = (unsigned long *) (regs->regs[29] + 16);
@@ -1571,44 +1829,56 @@ asmlinkage int irix_mmap64(struct pt_regs *regs)
flags = regs->regs[base + 7];
error = verify_area(VERIFY_READ, sp, (4 * sizeof(unsigned long)));
if(error)
- return error;
+ goto out;
fd = sp[0];
__get_user(off1, &sp[1]);
__get_user(off2, &sp[2]);
} else {
error = verify_area(VERIFY_READ, sp, (5 * sizeof(unsigned long)));
if(error)
- return error;
+ goto out;
__get_user(flags, &sp[0]);
__get_user(fd, &sp[1]);
__get_user(off1, &sp[2]);
__get_user(off2, &sp[3]);
}
- if(off1)
- return -EINVAL;
- return sys_mmap(addr, (size_t) len, prot, flags, fd, off2);
+ if(off1) {
+ error = -EINVAL;
+ goto out;
+ }
+ error = sys_mmap(addr, (size_t) len, prot, flags, fd, off2);
+
+out:
+ unlock_kernel();
+ return error;
}
asmlinkage int irix_dmi(struct pt_regs *regs)
{
+ lock_kernel();
printk("[%s:%d] Wheee.. irix_dmi()\n",
current->comm, current->pid);
+ unlock_kernel();
return -EINVAL;
}
asmlinkage int irix_pread(int fd, char *buf, int cnt, int off64,
int off1, int off2)
{
+ lock_kernel();
printk("[%s:%d] Wheee.. irix_pread(%d,%p,%d,%d,%d,%d)\n",
current->comm, current->pid, fd, buf, cnt, off64, off1, off2);
+ unlock_kernel();
return -EINVAL;
}
asmlinkage int irix_pwrite(int fd, char *buf, int cnt, int off64,
int off1, int off2)
{
+ lock_kernel();
printk("[%s:%d] Wheee.. irix_pwrite(%d,%p,%d,%d,%d,%d)\n",
current->comm, current->pid, fd, buf, cnt, off64, off1, off2);
+ unlock_kernel();
return -EINVAL;
}
@@ -1616,10 +1886,12 @@ asmlinkage int irix_sgifastpath(int cmd, unsigned long arg0, unsigned long arg1,
unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5)
{
+ lock_kernel();
printk("[%s:%d] Wheee.. irix_fastpath(%d,%08lx,%08lx,%08lx,%08lx,"
"%08lx,%08lx)\n",
current->comm, current->pid, cmd, arg0, arg1, arg2,
arg3, arg4, arg5);
+ unlock_kernel();
return -EINVAL;
}
@@ -1644,13 +1916,14 @@ asmlinkage int irix_statvfs64(char *fname, struct irix_statvfs64 *buf)
current->comm, current->pid, fname, buf);
error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
if(error)
- return error;
+ goto out;
error = namei(fname, &inode);
if(error)
- return error;
+ goto out;
if(!inode->i_sb->s_op->statfs) {
iput(inode);
- return -ENOSYS;
+ error = -ENOSYS;
+ goto out;
}
old_fs = get_fs(); set_fs(get_ds());
@@ -1678,7 +1951,11 @@ asmlinkage int irix_statvfs64(char *fname, struct irix_statvfs64 *buf)
for(i = 0; i < 32; i++)
__put_user(0, &buf->f_fstr[i]);
- return 0;
+ error = 0;
+
+out:
+ unlock_kernel();
+ return error;
}
asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs *buf)
@@ -1688,18 +1965,25 @@ asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs *buf)
struct file *file;
int error, old_fs, i;
+ lock_kernel();
printk("[%s:%d] Wheee.. irix_fstatvfs(%d,%p)\n",
current->comm, current->pid, fd, buf);
error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
if (error)
- return error;
- if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
- return -EBADF;
- if (!(inode = file->f_inode))
- return -ENOENT;
- if (!inode->i_sb->s_op->statfs)
- return -ENOSYS;
+ goto out;
+ if (fd >= NR_OPEN || !(file = current->files->fd[fd])) {
+ error = -EBADF;
+ goto out;
+ }
+ if (!(inode = file->f_inode)) {
+ error = -ENOENT;
+ goto out;
+ }
+ if (!inode->i_sb->s_op->statfs) {
+ error = -ENOSYS;
+ goto out;
+ }
old_fs = get_fs(); set_fs(get_ds());
inode->i_sb->s_op->statfs(inode->i_sb, &kbuf, sizeof(struct statfs));
@@ -1725,18 +2009,23 @@ asmlinkage int irix_fstatvfs64(int fd, struct irix_statvfs *buf)
for(i = 0; i < 32; i++)
__put_user(0, &buf->f_fstr[i]);
- return 0;
+ error = 0;
+
+out:
+ unlock_kernel();
+ return error;
}
asmlinkage int irix_getmountid(char *fname, unsigned long *midbuf)
{
int errno;
+ lock_kernel();
printk("[%s:%d] irix_getmountid(%s, %p)\n",
current->comm, current->pid, fname, midbuf);
errno = verify_area(VERIFY_WRITE, midbuf, (sizeof(unsigned long) * 4));
if(errno)
- return errno;
+ goto out;
/*
* The idea with this system call is that when trying to determine
@@ -1748,15 +2037,20 @@ asmlinkage int irix_getmountid(char *fname, unsigned long *midbuf)
__put_user(0, &midbuf[1]);
__put_user(0, &midbuf[2]);
__put_user(0, &midbuf[3]);
+ error = 0;
- return 0;
+out:
+ unlock_kernel();
+ return error;
}
asmlinkage int irix_nsproc(unsigned long entry, unsigned long mask,
unsigned long arg, unsigned long sp, int slen)
{
+ lock_kernel();
printk("[%s:%d] Wheee.. irix_nsproc(%08lx,%08lx,%08lx,%08lx,%d)\n",
current->comm, current->pid, entry, mask, arg, sp, slen);
+ unlock_kernel();
return -EINVAL;
}
@@ -1784,14 +2078,18 @@ static int irix_filldir32(void *__buf, const char *name, int namlen, off_t offse
struct irix_dirent32 *dirent;
struct irix_dirent32_callback *buf = (struct irix_dirent32_callback *)__buf;
unsigned short reclen = ROUND_UP32(NAME_OFFSET32(dirent) + namlen + 1);
+ int retval;
+ lock_kernel();
#ifdef DEBUG_GETDENTS
printk("\nirix_filldir32[reclen<%d>namlen<%d>count<%d>]",
reclen, namlen, buf->count);
#endif
buf->error = -EINVAL; /* only used if we fail.. */
- if (reclen > buf->count)
- return -EINVAL;
+ if (reclen > buf->count) {
+ retval = -EINVAL;
+ goto out;
+ }
dirent = buf->previous;
if (dirent)
__put_user(offset, &dirent->d_off);
@@ -1805,7 +2103,11 @@ static int irix_filldir32(void *__buf, const char *name, int namlen, off_t offse
buf->current_dir = dirent;
buf->count -= reclen;
- return 0;
+ retval = 0;
+
+out:
+ unlock_kernel();
+ return retval;
}
asmlinkage int irix_ngetdents(unsigned int fd, void * dirent, unsigned int count, int *eob)
@@ -1815,17 +2117,24 @@ asmlinkage int irix_ngetdents(unsigned int fd, void * dirent, unsigned int count
struct irix_dirent32_callback buf;
int error;
+ lock_kernel();
#ifdef DEBUG_GETDENTS
printk("[%s:%d] ngetdents(%d, %p, %d, %p) ", current->comm,
current->pid, fd, dirent, count, eob);
#endif
- if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
- return -EBADF;
- if (!file->f_op || !file->f_op->readdir)
- return -ENOTDIR;
+ if (fd >= NR_OPEN || !(file = current->files->fd[fd])) {
+ error = -EBADF;
+ goto out;
+ }
+ if (!file->f_op || !file->f_op->readdir) {
+ error = -ENOTDIR;
+ goto out;
+ }
if(verify_area(VERIFY_WRITE, dirent, count) ||
- verify_area(VERIFY_WRITE, eob, sizeof(*eob)))
- return -EFAULT;
+ verify_area(VERIFY_WRITE, eob, sizeof(*eob))) {
+ error = -EFAULT;
+ goto out;
+ }
__put_user(0, eob);
buf.current_dir = (struct irix_dirent32 *) dirent;
buf.previous = NULL;
@@ -1833,15 +2142,21 @@ asmlinkage int irix_ngetdents(unsigned int fd, void * dirent, unsigned int count
buf.error = 0;
error = file->f_op->readdir(file->f_inode, file, &buf, irix_filldir32);
if (error < 0)
- return error;
+ goto out
lastdirent = buf.previous;
- if (!lastdirent)
- return buf.error;
+ if (!lastdirent) {
+ error = buf.error;
+ goto out;
+ }
lastdirent->d_off = (u32) file->f_pos;
#ifdef DEBUG_GETDENTS
printk("eob=%d returning %d\n", *eob, count - buf.count);
#endif
- return count - buf.count;
+ error = count - buf.count;
+
+out:
+ unlock_kernel();
+ return error;
}
struct irix_dirent64 {
@@ -1868,10 +2183,14 @@ static int irix_filldir64(void * __buf, const char * name, int namlen,
struct irix_dirent64_callback * buf =
(struct irix_dirent64_callback *) __buf;
unsigned short reclen = ROUND_UP64(NAME_OFFSET64(dirent) + namlen + 1);
+ int retval;
+ lock_kernel();
buf->error = -EINVAL; /* only used if we fail.. */
- if (reclen > buf->count)
- return -EINVAL;
+ if (reclen > buf->count) {
+ retval = -EINVAL;
+ goto out;
+ }
dirent = buf->previous;
if (dirent)
__put_user(offset, &dirent->d_off);
@@ -1885,7 +2204,10 @@ static int irix_filldir64(void * __buf, const char * name, int namlen,
buf->curr = dirent;
buf->count -= reclen;
- return 0;
+ retval = 0;
+out:
+ unlock_kernel();
+ return retval;
}
asmlinkage int irix_getdents64(int fd, void *dirent, int cnt)
@@ -1895,18 +2217,27 @@ asmlinkage int irix_getdents64(int fd, void *dirent, int cnt)
struct irix_dirent64_callback buf;
int error;
+ lock_kernel();
#ifdef DEBUG_GETDENTS
printk("[%s:%d] getdents64(%d, %p, %d) ", current->comm,
current->pid, fd, dirent, cnt);
#endif
- if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
- return -EBADF;
- if (!file->f_op || !file->f_op->readdir)
- return -ENOTDIR;
- if(verify_area(VERIFY_WRITE, dirent, cnt))
- return -EFAULT;
- if(cnt < (sizeof(struct irix_dirent64) + 255))
- return -EINVAL;
+ if (fd >= NR_OPEN || !(file = current->files->fd[fd])) {
+ error = -EBADF;
+ goto out;
+ }
+ if (!file->f_op || !file->f_op->readdir) {
+ error = -ENOTDIR;
+ goto out;
+ }
+ if(verify_area(VERIFY_WRITE, dirent, cnt)) {
+ error = -EFAULT;
+ goto out;
+ }
+ if(cnt < (sizeof(struct irix_dirent64) + 255)) {
+ error = -EINVAL;
+ goto out;
+ }
buf.curr = (struct irix_dirent64 *) dirent;
buf.previous = NULL;
@@ -1914,15 +2245,21 @@ asmlinkage int irix_getdents64(int fd, void *dirent, int cnt)
buf.error = 0;
error = file->f_op->readdir(file->f_inode, file, &buf, irix_filldir64);
if (error < 0)
- return error;
+ goto out;
lastdirent = buf.previous;
- if (!lastdirent)
- return buf.error;
+ if (!lastdirent) {
+ error = buf.error;
+ goto out;
+ }
lastdirent->d_off = (u64) file->f_pos;
#ifdef DEBUG_GETDENTS
printk("returning %d\n", cnt - buf.count);
#endif
- return cnt - buf.count;
+ error = cnt - buf.count;
+
+out:
+ unlock_kernel();
+ return error;
}
asmlinkage int irix_ngetdents64(int fd, void *dirent, int cnt, int *eob)
@@ -1932,19 +2269,28 @@ asmlinkage int irix_ngetdents64(int fd, void *dirent, int cnt, int *eob)
struct irix_dirent64_callback buf;
int error;
+ lock_kernel();
#ifdef DEBUG_GETDENTS
printk("[%s:%d] ngetdents64(%d, %p, %d) ", current->comm,
current->pid, fd, dirent, cnt);
#endif
- if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
- return -EBADF;
- if (!file->f_op || !file->f_op->readdir)
- return -ENOTDIR;
+ if (fd >= NR_OPEN || !(file = current->files->fd[fd])) {
+ error = -EBADF;
+ goto out;
+ }
+ if (!file->f_op || !file->f_op->readdir) {
+ error = -ENOTDIR;
+ goto out;
+ }
if(verify_area(VERIFY_WRITE, dirent, cnt) ||
- verify_area(VERIFY_WRITE, eob, sizeof(*eob)))
- return -EFAULT;
- if(cnt < (sizeof(struct irix_dirent64) + 255))
- return -EINVAL;
+ verify_area(VERIFY_WRITE, eob, sizeof(*eob))) {
+ error = -EFAULT;
+ goto out;
+ }
+ if(cnt < (sizeof(struct irix_dirent64) + 255)) {
+ error = -EINVAL;
+ goto out;
+ }
*eob = 0;
buf.curr = (struct irix_dirent64 *) dirent;
@@ -1953,81 +2299,111 @@ asmlinkage int irix_ngetdents64(int fd, void *dirent, int cnt, int *eob)
buf.error = 0;
error = file->f_op->readdir(file->f_inode, file, &buf, irix_filldir64);
if (error < 0)
- return error;
+ goto out;
lastdirent = buf.previous;
- if (!lastdirent)
- return buf.error;
+ if (!lastdirent) {
+ error = buf.error;
+ goto out;
+ }
lastdirent->d_off = (u64) file->f_pos;
#ifdef DEBUG_GETDENTS
printk("eob=%d returning %d\n", *eob, cnt - buf.count);
#endif
- return cnt - buf.count;
+ error = cnt - buf.count;
+
+out:
+ unlock_kernel();
+ return error;
}
asmlinkage int irix_uadmin(unsigned long op, unsigned long func, unsigned long arg)
{
+ int retval;
+
+ lock_kernel();
switch(op) {
case 1:
/* Reboot */
printk("[%s:%d] irix_uadmin: Wants to reboot...\n",
current->comm, current->pid);
- return -EINVAL;
+ retval = -EINVAL;
+ goto out;
case 2:
/* Shutdown */
printk("[%s:%d] irix_uadmin: Wants to shutdown...\n",
current->comm, current->pid);
- return -EINVAL;
+ retval = -EINVAL;
+ goto out;
case 4:
/* Remount-root */
printk("[%s:%d] irix_uadmin: Wants to remount root...\n",
current->comm, current->pid);
- return -EINVAL;
+ retval = -EINVAL;
+ goto out;
case 8:
/* Kill all tasks. */
printk("[%s:%d] irix_uadmin: Wants to kill all tasks...\n",
current->comm, current->pid);
- return -EINVAL;
+ retval = -EINVAL;
+ goto out;
case 256:
/* Set magic mushrooms... */
printk("[%s:%d] irix_uadmin: Wants to set magic mushroom[%d]...\n",
current->comm, current->pid, (int) func);
- return -EINVAL;
+ retval = -EINVAL;
+ goto out;
default:
printk("[%s:%d] irix_uadmin: Unknown operation [%d]...\n",
current->comm, current->pid, (int) op);
- return -EINVAL;
+ retval = -EINVAL;
+ goto out;
};
+
+out:
+ unlock_kernel();
+ return retval;
}
asmlinkage int irix_utssys(char *inbuf, int arg, int type, char *outbuf)
{
+ int retval;
+
+ lock_kernel();
switch(type) {
case 0:
/* uname() */
- return irix_uname((struct iuname *)inbuf);
+ retval = irix_uname((struct iuname *)inbuf);
+ goto out;
case 2:
/* ustat() */
printk("[%s:%d] irix_utssys: Wants to do ustat()\n",
current->comm, current->pid);
- return -EINVAL;
+ retval = -EINVAL;
+ goto out;
case 3:
/* fusers() */
printk("[%s:%d] irix_utssys: Wants to do fusers()\n",
current->comm, current->pid);
- return -EINVAL;
+ retval = -EINVAL;
+ goto out;
default:
printk("[%s:%d] irix_utssys: Wants to do unknown type[%d]\n",
current->comm, current->pid, (int) type);
- return -EINVAL;
+ retval = -EINVAL;
+ goto out;
}
+
+out:
+ unlock_kernel();
+ return retval;
}
#undef DEBUG_FCNTL
@@ -2039,6 +2415,7 @@ asmlinkage int irix_fcntl(int fd, int cmd, int arg)
{
int retval;
+ lock_kernel();
#ifdef DEBUG_FCNTL
printk("[%s:%d] irix_fcntl(%d, %d, %d) ", current->comm,
current->pid, fd, cmd, arg);
@@ -2048,53 +2425,67 @@ asmlinkage int irix_fcntl(int fd, int cmd, int arg)
#ifdef DEBUG_FCNTL
printk("%d\n", retval);
#endif
+ unlock_kernel();
return retval;
}
asmlinkage int irix_ulimit(int cmd, int arg)
{
+ lock_kernel();
switch(cmd) {
case 1:
printk("[%s:%d] irix_ulimit: Wants to get file size limit.\n",
current->comm, current->pid);
- return -EINVAL;
+ retval = -EINVAL;
+ goto out;
case 2:
printk("[%s:%d] irix_ulimit: Wants to set file size limit.\n",
current->comm, current->pid);
- return -EINVAL;
+ retval = -EINVAL;
+ goto out;
case 3:
printk("[%s:%d] irix_ulimit: Wants to get brk limit.\n",
current->comm, current->pid);
- return -EINVAL;
+ retval = -EINVAL;
+ goto out;
case 4:
#if 0
printk("[%s:%d] irix_ulimit: Wants to get fd limit.\n",
current->comm, current->pid);
- return -EINVAL;
+ retval = -EINVAL;
+ goto out;
#endif
- return current->rlim[RLIMIT_NOFILE].rlim_cur;
+ retval = current->rlim[RLIMIT_NOFILE].rlim_cur;
+ goto out;
case 5:
printk("[%s:%d] irix_ulimit: Wants to get txt offset.\n",
current->comm, current->pid);
- return -EINVAL;
+ retval = -EINVAL;
+ goto out;
default:
printk("[%s:%d] irix_ulimit: Unknown command [%d].\n",
current->comm, current->pid, cmd);
- return -EINVAL;
+ retval = -EINVAL;
+ goto out;
}
+out:
+ unlock_kernel();
+ return retval;
}
asmlinkage int irix_unimp(struct pt_regs *regs)
{
+ lock_kernel();
printk("irix_unimp [%s:%d] v0=%d v1=%d a0=%08lx a1=%08lx a2=%08lx "
"a3=%08lx\n", current->comm, current->pid,
(int) regs->regs[2], (int) regs->regs[3],
regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]);
+ unlock_kernel();
return -ENOSYS;
}
diff --git a/arch/mips/kernel/sysmips.c b/arch/mips/kernel/sysmips.c
index 4aff0bc61..c5e394d56 100644
--- a/arch/mips/kernel/sysmips.c
+++ b/arch/mips/kernel/sysmips.c
@@ -10,6 +10,8 @@
#include <linux/errno.h>
#include <linux/linkage.h>
#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/utsname.h>
@@ -19,12 +21,6 @@
#include <asm/sysmips.h>
#include <asm/uaccess.h>
-static inline size_t
-strnlen_user(const char *s, size_t count)
-{
- return strnlen(s, count);
-}
-
/*
* How long a hostname can we get from user space?
* -EFAULT if invalid area or too long
@@ -53,44 +49,65 @@ sys_sysmips(int cmd, int arg1, int arg2, int arg3)
{
int *p;
char *name;
- int flags, tmp, len, retval = -EINVAL;
+ int flags, tmp, len, retval;
+ lock_kernel();
switch(cmd)
{
case SETNAME:
- if (!suser())
- return -EPERM;
+ if (!suser()) {
+ retval = -EPERM;
+ goto out;
+ }
name = (char *) arg1;
- len = get_max_hostname((unsigned long)name);
- if (retval < 0)
- return len;
- len = strnlen_user(name, retval);
+ len = strlen_user(name);
+ if (len < 0)
+ retval = len;
+ goto out;
if (len == 0 || len > __NEW_UTS_LEN)
- return -EINVAL;
+ retval = -EINVAL;
+ goto out;
copy_from_user(system_utsname.nodename, name, len);
system_utsname.nodename[len] = '\0';
- return 0;
+ retval = 0;
+ goto out;
+
case MIPS_ATOMIC_SET:
+ /* This is broken in case of page faults and SMP ...
+ Risc/OS fauls after maximum 20 tries with EAGAIN. */
p = (int *) arg1;
retval = verify_area(VERIFY_WRITE, p, sizeof(*p));
- if(retval)
- return -EINVAL;
+ if (retval)
+ goto out;
save_flags(flags);
cli();
retval = *p;
*p = arg2;
restore_flags(flags);
- return retval;
+ goto out;
+
case MIPS_FIXADE:
tmp = current->tss.mflags & ~3;
current->tss.mflags = tmp | (arg1 & 3);
retval = 0;
- break;
+ goto out;
+
case FLUSH_CACHE:
flush_cache_all();
- break;
+ retval = 0;
+ goto out;
+
+ case MIPS_RDNVRAM:
+ retval = -EIO;
+ goto out;
+
+ default:
+ retval = -EINVAL;
+ goto out;
}
+out:
+ unlock_kernel();
return retval;
}
@@ -102,36 +119,3 @@ sys_cachectl(char *addr, int nbytes, int op)
{
return -ENOSYS;
}
-
-/* For emulation of various binary types, and their shared libs,
- * we need this.
- */
-
-extern int do_open_namei(const char *pathname, int flag, int mode,
- struct inode **res_inode, struct inode *base);
-
-/* Only one at this time. */
-#define IRIX32_EMUL "/usr/gnemul/irix"
-
-int open_namei(const char *pathname, int flag, int mode,
- struct inode **res_inode, struct inode *base)
-{
- if(!base && (current->personality == PER_IRIX32) &&
- *pathname == '/') {
- struct inode *emul_ino;
- const char *p = pathname;
- char *emul_path = IRIX32_EMUL;
- int v;
-
- while (*p == '/')
- p++;
-
- if(do_open_namei (emul_path, flag, mode, &emul_ino, NULL) >= 0 &&
- emul_ino) {
- v = do_open_namei (p, flag, mode, res_inode, emul_ino);
- if(v >= 0)
- return v;
- }
- }
- return do_open_namei (pathname, flag, mode, res_inode, base);
-}
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 2dd1d54ee..aa4547456 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -22,6 +22,11 @@
#include <linux/mc146818rtc.h>
#include <linux/timex.h>
+extern volatile unsigned long lost_ticks;
+
+/* change this if you have some constant time drift */
+#define USECS_PER_JIFFY (1000020/HZ)
+
/* This function must be called with interrupts disabled
* It was inspired by Steve McCanne's microtime-i386 for BSD. -- jrs
*
@@ -59,22 +64,64 @@
static unsigned long do_slow_gettimeoffset(void)
{
int count;
- unsigned long offset = 0;
+
+ static int count_p = LATCH; /* for the first call after boot */
+ static unsigned long jiffies_p = 0;
+
+ /*
+ * cache volatile jiffies temporarily; we have IRQs turned off.
+ */
+ unsigned long jiffies_t;
/* timer count may underflow right here */
outb_p(0x00, 0x43); /* latch the count ASAP */
+
count = inb_p(0x40); /* read the latched count */
- count |= inb(0x40) << 8;
- /* we know probability of underflow is always MUCH less than 1% */
- if (count > (LATCH - LATCH/100)) {
- /* check for pending timer interrupt */
- outb_p(0x0a, 0x20);
- if (inb(0x20) & 1)
- offset = TICK_SIZE;
- }
+
+ /*
+ * We do this guaranteed double memory access instead of a _p
+ * postfix in the previous port access. Wheee, hackady hack
+ */
+ jiffies_t = jiffies;
+
+ count |= inb_p(0x40) << 8;
+
+ /*
+ * avoiding timer inconsistencies (they are rare, but they happen)...
+ * there are two kinds of problems that must be avoided here:
+ * 1. the timer counter underflows
+ * 2. hardware problem with the timer, not giving us continuous time,
+ * the counter does small "jumps" upwards on some Pentium systems,
+ * (see c't 95/10 page 335 for Neptun bug.)
+ */
+
+ if( jiffies_t == jiffies_p ) {
+ if( count > count_p ) {
+ /* the nutcase */
+
+ outb_p(0x0A, 0x20);
+
+ /* assumption about timer being IRQ1 */
+ if( inb(0x20) & 0x01 ) {
+ /*
+ * We cannot detect lost timer interrupts ...
+ * well, thats why we call them lost, dont we? :)
+ * [hmm, on the Pentium and Alpha we can ... sort of]
+ */
+ count -= LATCH;
+ } else {
+ printk("do_slow_gettimeoffset(): hardware timer problem?\n");
+ }
+ }
+ } else
+ jiffies_p = jiffies_t;
+
+ count_p = count;
+
count = ((LATCH-1) - count) * TICK_SIZE;
count = (count + LATCH/2) / LATCH;
- return offset + count;
+
+ return count;
}
static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
@@ -90,11 +137,20 @@ void do_gettimeofday(struct timeval *tv)
cli();
*tv = xtime;
tv->tv_usec += do_gettimeoffset();
+
+ /*
+ * xtime is atomically updated in timer_bh. lost_ticks is
+ * nonzero if the timer bottom half hasnt executed yet.
+ */
+ if (lost_ticks)
+ tv->tv_usec += USECS_PER_JIFFY;
+
+ restore_flags(flags);
+
if (tv->tv_usec >= 1000000) {
tv->tv_usec -= 1000000;
tv->tv_sec++;
}
- restore_flags(flags);
}
void do_settimeofday(struct timeval *tv)
@@ -167,7 +223,7 @@ static int set_rtc_mmss(unsigned long nowtime)
/* The following flags have to be released exactly in this order,
* otherwise the DS12887 (popular MC146818A clone with integrated
- * battery and crystal) will not reset the oscillator and will not
+ * battery and quartz) will not reset the oscillator and will not
* update precisely 500 ms later. You won't find this mentioned in
* the Dallas Semiconductor data sheets, but who believes data
* sheets anyway ... -- Markus Kuhn
@@ -205,7 +261,7 @@ static void timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
basically because we don't yet share IRQ's around. This message is
rigged to be safe on the 386 - basically it's a hack, so don't look
closely for now.. */
- smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0);
+ /*smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0); */
}
/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
@@ -281,7 +337,7 @@ void time_init(void)
if ((year += 1900) < 1970)
year += 100;
#else
- /* true for all MIPS machines? */
+ /* Acer PICA clock starts from 1980. True for all MIPS machines? */
year += 1980;
#endif
xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 20cd6fe06..17b1f9a28 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -18,6 +18,8 @@
*/
#include <linux/config.h>
#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
#include <asm/branch.h>
#include <asm/cachectl.h>
@@ -93,34 +95,15 @@ int kstack_depth_to_print = 24;
* This routine abuses get_user()/put_user() to reference pointers
* with at least a bit of error checking ...
*/
-void die_if_kernel(char * str, struct pt_regs * regs, long err)
+void show_registers(char * str, struct pt_regs * regs, long err)
{
int i;
int *stack;
u32 *sp, *pc, addr, module_start, module_end;
extern char start_kernel, _etext;
- /*
- * Just return if in user mode.
- * XXX
- */
-#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
- if (!((regs)->cp0_status & 0x4))
- return;
-#endif
-#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4)
- if (!(regs->cp0_status & 0x18))
- return;
-#endif
-
- /*
- * Yes, these double casts are required ...
- */
- sp = (u32 *)(unsigned long)regs->regs[29];
- pc = (u32 *)(unsigned long)regs->cp0_epc;
-
- console_verbose();
- printk("%s: %08lx\n", str, err );
+ sp = (u32 *)regs->regs[29];
+ pc = (u32 *)regs->cp0_epc;
show_regs(regs);
@@ -189,6 +172,26 @@ void die_if_kernel(char * str, struct pt_regs * regs, long err)
do_exit(SIGSEGV);
}
+void die_if_kernel(const char * str, struct pt_regs * regs, long err)
+{
+ /*
+ * Just return if in user mode.
+ * XXX
+ */
+#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2)
+ if (!((regs)->cp0_status & 0x4))
+ return;
+#endif
+#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4)
+ if (!(regs->cp0_status & 0x18))
+ return;
+#endif
+ console_verbose();
+ printk("%s: %04lx\n", str, err & 0xffff);
+ show_regs(regs);
+ do_exit(SIGSEGV);
+}
+
static void default_be_board_handler(struct pt_regs *regs)
{
/*
@@ -199,32 +202,44 @@ static void default_be_board_handler(struct pt_regs *regs)
void do_ibe(struct pt_regs *regs)
{
+ lock_kernel();
ibe_board_handler(regs);
+ unlock_kernel();
}
void do_dbe(struct pt_regs *regs)
{
+ lock_kernel();
dbe_board_handler(regs);
+ unlock_kernel();
}
void do_ov(struct pt_regs *regs)
{
+ lock_kernel();
#ifdef CONF_DEBUG_EXCEPTIONS
show_regs(regs);
#endif
if (compute_return_epc(regs))
- return;
+ goto out;
force_sig(SIGFPE, current);
+out:
+ unlock_kernel();
}
void do_fpe(struct pt_regs *regs, unsigned int fcr31)
{
+ lock_kernel();
#ifdef CONF_DEBUG_EXCEPTIONS
show_regs(regs);
#endif
+ printk("Caught floating exception at epc == %08lx, fcr31 == %08x\n",
+ regs->cp0_epc, fcr31);
if (compute_return_epc(regs))
- return;
+ goto out;
force_sig(SIGFPE, current);
+out:
+ unlock_kernel();
}
static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode)
@@ -262,6 +277,7 @@ void do_bp(struct pt_regs *regs)
{
unsigned int opcode, bcode;
+ lock_kernel();
/*
* There is the ancient bug in the MIPS assemblers that the break
* code starts left to bit 16 instead to bit 6 in the opcode.
@@ -271,87 +287,106 @@ void do_bp(struct pt_regs *regs)
printk("BREAKPOINT at %08lx\n", regs->cp0_epc);
#endif
if (get_insn_opcode(regs, &opcode))
- return;
+ goto out;
bcode = ((opcode >> 16) & ((1 << 20) - 1));
do_bp_and_tr(regs, "bp", bcode);
if (compute_return_epc(regs))
- return;
+ goto out;
+out:
+ unlock_kernel();
}
void do_tr(struct pt_regs *regs)
{
unsigned int opcode, bcode;
+ lock_kernel();
if (get_insn_opcode(regs, &opcode))
- return;
+ goto out;
bcode = ((opcode >> 6) & ((1 << 20) - 1));
do_bp_and_tr(regs, "tr", bcode);
+out:
+ unlock_kernel();
}
void do_ri(struct pt_regs *regs)
{
+ lock_kernel();
#ifdef CONF_DEBUG_EXCEPTIONS
show_regs(regs);
#endif
printk("[%s:%d] Illegal instruction at %08lx ra=%08lx\n",
current->comm, current->pid, regs->cp0_epc, regs->regs[31]);
if (compute_return_epc(regs))
- return;
+ goto out;
force_sig(SIGILL, current);
+out:
+ unlock_kernel();
}
void do_cpu(struct pt_regs *regs)
{
unsigned int cpid;
+ lock_kernel();
cpid = (regs->cp0_cause >> CAUSEB_CE) & 3;
if (cpid == 1)
{
regs->cp0_status |= ST0_CU1;
- return;
+ goto out;
}
force_sig(SIGILL, current);
+out:
+ unlock_kernel();
}
void do_vcei(struct pt_regs *regs)
{
+ lock_kernel();
/*
* Only possible on R4[04]00[SM]C. No handler because I don't have
* such a cpu. Theory says this exception doesn't happen.
*/
panic("Caught VCEI exception - should not happen");
+ unlock_kernel();
}
void do_vced(struct pt_regs *regs)
{
+ lock_kernel();
/*
* Only possible on R4[04]00[SM]C. No handler because I don't have
* such a cpu. Theory says this exception doesn't happen.
*/
panic("Caught VCE exception - should not happen");
+ unlock_kernel();
}
void do_watch(struct pt_regs *regs)
{
+ lock_kernel();
/*
* We use the watch exception where available to detect stack
* overflows.
*/
show_regs(regs);
panic("Caught WATCH exception - probably caused by stack overflow.");
+ unlock_kernel();
}
void do_reserved(struct pt_regs *regs)
{
+ lock_kernel();
/*
* Game over - no way to handle this if it ever occurs.
* Most probably caused by a new unknown cpu type or
* after another deadly hard/software error.
*/
panic("Caught reserved exception - should not happen.");
+ unlock_kernel();
}
static void watch_init(unsigned long cputype)
@@ -365,7 +400,7 @@ static void watch_init(unsigned long cputype)
case CPU_R4000PC:
case CPU_R4400PC:
case CPU_R4200:
- /* case CPU_R4300: */
+ case CPU_R4300:
set_except_vector(23, handle_watch);
watch_available = 1;
break;
@@ -454,7 +489,7 @@ void trap_init(void)
case CPU_R4000PC:
case CPU_R4400PC:
case CPU_R4200:
- /* case CPU_R4300: */
+ case CPU_R4300:
/* case CPU_R4640: */
case CPU_R4600:
case CPU_R5000:
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index ba3a612fa..696244b6c 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -85,6 +85,9 @@
*/
#include <linux/mm.h>
#include <linux/signal.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+
#include <asm/branch.h>
#include <asm/byteorder.h>
#include <asm/inst.h>
@@ -169,7 +172,7 @@ emulate_load_store_insn(struct pt_regs *regs, unsigned long addr, unsigned long
".section\t__ex_table,\"a\"\n\t"
STR(PTR)"\t1b,%2\n\t"
STR(PTR)"\t2b,%2\n\t"
- ".text"
+ ".previous"
:"=&r" (value)
:"r" (addr), "i" (&&fault)
:"$1");
@@ -190,7 +193,7 @@ emulate_load_store_insn(struct pt_regs *regs, unsigned long addr, unsigned long
".section\t__ex_table,\"a\"\n\t"
STR(PTR)"\t1b,%2\n\t"
STR(PTR)"\t2b,%2\n\t"
- ".text"
+ ".previous"
:"=&r" (value)
:"r" (addr), "i" (&&fault));
regs->regs[insn.i_format.rt] = value;
@@ -214,7 +217,7 @@ emulate_load_store_insn(struct pt_regs *regs, unsigned long addr, unsigned long
".section\t__ex_table,\"a\"\n\t"
STR(PTR)"\t1b,%2\n\t"
STR(PTR)"\t2b,%2\n\t"
- ".text"
+ ".previous"
:"=&r" (value)
:"r" (addr), "i" (&&fault)
:"$1");
@@ -235,7 +238,7 @@ emulate_load_store_insn(struct pt_regs *regs, unsigned long addr, unsigned long
".section\t__ex_table,\"a\"\n\t"
STR(PTR)"\t1b,%2\n\t"
STR(PTR)"\t2b,%2\n\t"
- ".text"
+ ".previous"
:"=&r" (value)
:"r" (addr), "i" (&&fault));
value &= 0xffffffff;
@@ -258,7 +261,7 @@ emulate_load_store_insn(struct pt_regs *regs, unsigned long addr, unsigned long
".section\t__ex_table,\"a\"\n\t"
STR(PTR)"\t1b,%2\n\t"
STR(PTR)"\t2b,%2\n\t"
- ".text"
+ ".previous"
:"=&r" (value)
:"r" (addr), "i" (&&fault));
regs->regs[insn.i_format.rt] = value;
@@ -285,7 +288,7 @@ emulate_load_store_insn(struct pt_regs *regs, unsigned long addr, unsigned long
".section\t__ex_table,\"a\"\n\t"
STR(PTR)"\t1b,%2\n\t"
STR(PTR)"\t2b,%2\n\t"
- ".text"
+ ".previous"
: /* no outputs */
:"r" (value), "r" (addr), "i" (&&fault)
:"$1");
@@ -306,7 +309,7 @@ emulate_load_store_insn(struct pt_regs *regs, unsigned long addr, unsigned long
".section\t__ex_table,\"a\"\n\t"
STR(PTR)"\t1b,%2\n\t"
STR(PTR)"\t2b,%2\n\t"
- ".text"
+ ".previous"
: /* no outputs */
:"r" (value), "r" (addr), "i" (&&fault));
return;
@@ -328,7 +331,7 @@ emulate_load_store_insn(struct pt_regs *regs, unsigned long addr, unsigned long
".section\t__ex_table,\"a\"\n\t"
STR(PTR)"\t1b,%2\n\t"
STR(PTR)"\t2b,%2\n\t"
- ".text"
+ ".previous"
: /* no outputs */
:"r" (value), "r" (addr), "i" (&&fault));
return;
@@ -406,6 +409,7 @@ do_ade(struct pt_regs *regs)
register_t badvaddr __attribute__ ((unused)) = regs->cp0_badvaddr;
char *adels;
+ lock_kernel();
adels = (((regs->cp0_cause & CAUSEF_EXCCODE) >>
CAUSEB_EXCCODE) == 4) ? "adel" : "ades";
@@ -444,11 +448,11 @@ do_ade(struct pt_regs *regs)
#endif /* CONF_LOG_UNALIGNED_ACCESSES */
if (compute_return_epc(regs))
- return;
+ goto out;
if(current->tss.mflags & MF_FIXADE) {
pc += ((regs->cp0_cause & CAUSEF_BD) ? 4 : 0);
fix_ade(regs, pc);
- return;
+ goto out;
}
#ifdef CONF_DEBUG_EXCEPTIONS
@@ -456,4 +460,8 @@ do_ade(struct pt_regs *regs)
#endif
force_sig(SIGBUS, current);
+
+out:
+ unlock_kernel();
+ return;
}