patch-2.1.34 linux/arch/sparc64/kernel/sys_sparc.c

Next file: linux/arch/sparc64/kernel/sys_sparc32.c
Previous file: linux/arch/sparc64/kernel/sparcelf32.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.33/linux/arch/sparc64/kernel/sys_sparc.c linux/arch/sparc64/kernel/sys_sparc.c
@@ -0,0 +1,270 @@
+/* $Id: sys_sparc.c,v 1.1 1997/04/09 08:25:18 jj Exp $
+ * linux/arch/sparc64/kernel/sys_sparc.c
+ *
+ * This file contains various random system calls that
+ * have a non-standard calling sequence on the Linux/sparc
+ * platform.
+ */
+
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/stat.h>
+#include <linux/mman.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+
+#include <asm/uaccess.h>
+#include <asm/ipc.h>
+
+/* XXX Make this per-binary type, this way we can detect the type of
+ * XXX a binary.  Every Sparc executable calls this very early on.
+ */
+asmlinkage unsigned long sys_getpagesize(void)
+{
+	return PAGE_SIZE;
+}
+
+extern asmlinkage unsigned long sys_brk(unsigned long brk);
+
+asmlinkage unsigned long sparc_brk(unsigned long brk)
+{
+	unsigned long ret;
+
+	lock_kernel();
+	if(brk >= 0x80000000000ULL) {	/* VM hole */
+		ret = current->mm->brk;
+		goto out;
+	}
+	ret = sys_brk(brk);
+out:
+	unlock_kernel();
+	return ret;
+}
+
+/*
+ * sys_pipe() is the normal C calling standard for creating
+ * a pipe. It's not the way unix traditionally does this, though.
+ */
+asmlinkage int sparc_pipe(struct pt_regs *regs)
+{
+	int fd[2];
+	int error;
+
+	lock_kernel();
+	error = do_pipe(fd);
+	if (error)
+		goto out;
+	regs->u_regs[UREG_I1] = fd[1];
+	error = fd[0];
+out:
+	unlock_kernel();
+	return error;
+}
+
+/*
+ * sys_ipc() is the de-multiplexer for the SysV IPC calls..
+ *
+ * This is really horribly ugly.
+ */
+
+asmlinkage int sys_ipc (unsigned call, int first, int second, unsigned long third, void *ptr, long fifth)
+{
+	int err;
+
+	lock_kernel();
+	/* No need for backward compatibility. We can start fresh... */
+
+	if (call <= SEMCTL)
+		switch (call) {
+		case SEMOP:
+			err = sys_semop (first, (struct sembuf *)ptr, second);
+			goto out;
+		case SEMGET:
+			err = sys_semget (first, second, (int)third);
+			goto out;
+		case SEMCTL: {
+			union semun fourth;
+			err = -EINVAL;
+			if (!ptr)
+				goto out;
+			err = -EFAULT;
+			if(get_user(fourth.__pad, (void **)ptr))
+				goto out;
+			err = sys_semctl (first, second, (int)third, fourth);
+			goto out;
+			}
+		default:
+			err = -EINVAL;
+			goto out;
+		}
+	if (call <= MSGCTL) 
+		switch (call) {
+		case MSGSND:
+			err = sys_msgsnd (first, (struct msgbuf *) ptr, 
+					  second, (int)third);
+			goto out;
+		case MSGRCV:
+			err = sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, (int)third);
+			goto out;
+		case MSGGET:
+			err = sys_msgget ((key_t) first, second);
+			goto out;
+		case MSGCTL:
+			err = sys_msgctl (first, second, (struct msqid_ds *) ptr);
+			goto out;
+		default:
+			err = -EINVAL;
+			goto out;
+		}
+	if (call <= SHMCTL) 
+		switch (call) {
+		case SHMAT:
+			err = sys_shmat (first, (char *) ptr, second, (ulong *) third);
+			goto out;
+		case SHMDT:
+			err = sys_shmdt ((char *)ptr);
+			goto out;
+		case SHMGET:
+			err = sys_shmget (first, second, (int)third);
+			goto out;
+		case SHMCTL:
+			err = sys_shmctl (first, second, (struct shmid_ds *) ptr);
+			goto out;
+		default:
+			err = -EINVAL;
+			goto out;
+		}
+	else
+		err = -EINVAL;
+out:
+	unlock_kernel();
+	return err;
+}
+
+extern unsigned long get_unmapped_area(unsigned long addr, unsigned long len);
+
+/* Linux version of mmap */
+asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
+	unsigned long prot, unsigned long flags, unsigned long fd,
+	unsigned long off)
+{
+	struct file * file = NULL;
+	unsigned long retval = -EBADF;
+
+	lock_kernel();
+	if (!(flags & MAP_ANONYMOUS)) {
+		if (fd >= NR_OPEN || !(file = current->files->fd[fd])){
+			goto out;
+	    }
+	}
+	retval = -ENOMEM;
+	if(!(flags & MAP_FIXED) && !addr) {
+		addr = get_unmapped_area(addr, len);
+		if(!addr){
+			goto out;
+		}
+	}
+
+	/* See asm-sparc64/uaccess.h */
+	retval = -EINVAL;
+	if((len > (TASK_SIZE - PAGE_SIZE)) || (addr > (TASK_SIZE-len-PAGE_SIZE)))
+		goto out;
+
+	if(addr >= 0x80000000000ULL) {
+		retval = current->mm->brk;
+		goto out;
+	}
+
+	retval = do_mmap(file, addr, len, prot, flags, off);
+out:
+	unlock_kernel();
+	return retval;
+}
+
+/* we come to here via sys_nis_syscall so it can setup the regs argument */
+asmlinkage unsigned long
+c_sys_nis_syscall (struct pt_regs *regs)
+{
+	lock_kernel();
+	printk ("Unimplemented SPARC system call %ld\n",regs->u_regs[1]);
+	show_regs (regs);
+	unlock_kernel();
+	return -ENOSYS;
+}
+
+/* #define DEBUG_SPARC_BREAKPOINT */
+
+asmlinkage void
+sparc_breakpoint (struct pt_regs *regs)
+{
+	lock_kernel();
+#ifdef DEBUG_SPARC_BREAKPOINT
+        printk ("TRAP: Entering kernel PC=%lx, nPC=%lx\n", regs->tpc, regs->tnpc);
+#endif
+	force_sig(SIGTRAP, current);
+#ifdef DEBUG_SPARC_BREAKPOINT
+	printk ("TRAP: Returning to space: PC=%lx nPC=%lx\n", regs->tpc, regs->tnpc);
+#endif
+	unlock_kernel();
+}
+
+extern void check_pending(int signum);
+
+asmlinkage int
+sparc_sigaction (int signum, const struct sigaction *action, struct sigaction *oldaction)
+{
+	struct sigaction new_sa, *p;
+	int err = -EINVAL;
+
+	lock_kernel();
+	if(signum < 0) {
+		current->tss.new_signal = 1;
+		signum = -signum;
+	}
+
+	if (signum<1 || signum>32)
+		goto out;
+	p = signum - 1 + current->sig->action;
+	if (action) {
+		err = -EINVAL;
+		if (signum==SIGKILL || signum==SIGSTOP)
+			goto out;
+		err = -EFAULT;
+		if(copy_from_user(&new_sa, action, sizeof(struct sigaction)))
+			goto out;	
+		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)
+				goto out;
+		}
+	}
+
+	if (oldaction) {
+		err = -EFAULT;
+		if (copy_to_user(oldaction, p, sizeof(struct sigaction)))
+			goto out;	
+	}
+
+	if (action) {
+		*p = new_sa;
+		check_pending(signum);
+	}
+
+	err = 0;
+out:
+	unlock_kernel();
+	return err;
+}
+
+/* only AP+ systems have sys_aplib */
+asmlinkage int sys_aplib(void)
+{
+	return -ENOSYS;
+}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov