summaryrefslogtreecommitdiffstats
path: root/arch/sparc64/solaris
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-09-12 01:29:55 +0000
committerRalf Baechle <ralf@linux-mips.org>1997-09-12 01:29:55 +0000
commit545f435ebcfd94a1e7c20b46efe81b4d6ac4e698 (patch)
treee9ce4bc598d06374bda906f18365984bf22a526a /arch/sparc64/solaris
parent4291a610eef89d0d5c69d9a10ee6560e1aa36c74 (diff)
Merge with Linux 2.1.55. More bugfixes and goodies from my private
CVS archive.
Diffstat (limited to 'arch/sparc64/solaris')
-rw-r--r--arch/sparc64/solaris/Makefile26
-rw-r--r--arch/sparc64/solaris/conv.h28
-rw-r--r--arch/sparc64/solaris/entry64.S202
-rw-r--r--arch/sparc64/solaris/fs.c711
-rw-r--r--arch/sparc64/solaris/ioctl.c316
-rw-r--r--arch/sparc64/solaris/ipc.c122
-rw-r--r--arch/sparc64/solaris/misc.c463
-rw-r--r--arch/sparc64/solaris/signal.c419
-rw-r--r--arch/sparc64/solaris/signal.h109
-rw-r--r--arch/sparc64/solaris/socksys.c127
-rw-r--r--arch/sparc64/solaris/systbl.S289
11 files changed, 2812 insertions, 0 deletions
diff --git a/arch/sparc64/solaris/Makefile b/arch/sparc64/solaris/Makefile
new file mode 100644
index 000000000..56d252962
--- /dev/null
+++ b/arch/sparc64/solaris/Makefile
@@ -0,0 +1,26 @@
+#
+# Makefile for the Solaris binary emulation.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definition is now in the main makefile...
+
+O_TARGET := solaris.o
+O_OBJS := entry64.o fs.o misc.o signal.o systbl.o ioctl.o ipc.o socksys.o
+ifeq ($(CONFIG_SOLARIS_EMUL),m)
+M_OBJS := $(O_TARGET)
+endif
+
+.S.s:
+ $(CPP) -D__ASSEMBLY__ -ansi $< -o $*.s
+
+.S.o:
+ $(CC) -D__ASSEMBLY__ -ansi -c $< -o $*.o
+
+ifneq ($(CONFIG_SOLARIS_EMUL),y)
+do_it_all:
+endif
+
+include $(TOPDIR)/Rules.make
diff --git a/arch/sparc64/solaris/conv.h b/arch/sparc64/solaris/conv.h
new file mode 100644
index 000000000..c806d3dc1
--- /dev/null
+++ b/arch/sparc64/solaris/conv.h
@@ -0,0 +1,28 @@
+/* $Id: conv.h,v 1.2 1997/09/03 12:29:13 jj Exp $
+ * conv.h: Utility macros for Solaris emulation
+ *
+ * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+/* #define DEBUG_SOLARIS */
+
+#ifndef __ASSEMBLY__
+
+#include <asm/unistd.h>
+
+/* As gcc will warn about casting u32 to some ptr, we have to cast it to
+ * unsigned long first, and that's what is A() for.
+ * You just do (void *)A(x), instead of having to
+ * type (void *)((unsigned long)x) or instead of just (void *)x, which will
+ * produce warnings.
+ */
+#define A(x) ((unsigned long)x)
+
+extern unsigned sys_call_table[];
+extern unsigned sys_call_table32[];
+extern unsigned sunos_sys_table[];
+
+#define SYS(name) ((long)sys_call_table[__NR_##name])
+#define SUNOS(x) ((long)sunos_sys_table[x])
+
+#endif /* __ASSEMBLY__ */
diff --git a/arch/sparc64/solaris/entry64.S b/arch/sparc64/solaris/entry64.S
new file mode 100644
index 000000000..e983010d1
--- /dev/null
+++ b/arch/sparc64/solaris/entry64.S
@@ -0,0 +1,202 @@
+/* $Id: entry64.S,v 1.3 1997/09/03 12:29:12 jj Exp $
+ * entry64.S: Solaris syscall emulation entry point.
+ *
+ * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
+ */
+
+#include <linux/errno.h>
+
+#include <asm/head.h>
+#include <asm/asi.h>
+#include <asm/smp.h>
+#include <asm/ptrace.h>
+#include <asm/page.h>
+#include <asm/signal.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+
+#include "conv.h"
+
+#define NR_SYSCALLS 256
+
+ .text
+solaris_syscall_trace:
+ call syscall_trace
+ nop
+ mov %i0, %o0
+ mov %i1, %o1
+ mov %i2, %o2
+ mov %i3, %o3
+ b,pt %xcc, 2f
+ mov %i4, %o4
+
+solaris_sucks:
+/* Solaris is a big system which needs to be able to do all the things
+ * in Inf+1 different ways */
+ add %i6, 0x5c, %o0
+ mov %i0, %g1
+ mov %i1, %i0
+ mov %i2, %i1
+ srl %o0, 0, %o0
+ mov %i3, %i2
+ mov %i4, %i3
+ mov %i5, %i4
+ ba,pt %xcc, solaris_sparc_syscall
+exen: lduwa [%o0] ASI_S, %i5
+
+exenf: ba,pt %xcc, solaris_sparc_syscall
+ clr %i5
+
+/* For shared binaries, binfmt_elf32 already sets up personality
+ and exec_domain. This is to handle static binaries as well */
+solaris_reg:
+ call solaris_register
+ nop
+ ba,pt %xcc, 1f
+ mov %i0, %o0
+
+linux_syscall_for_solaris:
+ sll %l7, 2, %l4
+ ba,pt %xcc, 10f
+ lduw [%l6 + %l4], %l7
+
+ /* Solaris system calls enter here... */
+ .align 32
+ .globl solaris_sparc_syscall
+solaris_sparc_syscall:
+#ifdef DEBUG_SOLARIS
+ mov %g1, %o0
+ call entry_printk
+ add %sp, STACK_BIAS + REGWIN_SZ, %o1
+#endif
+ ldub [%g6 + AOFF_task_personality + ASIZ_task_personality - 1], %l0
+ cmp %g1, 255
+ bg,pn %icc, solaris_unimplemented
+ srl %g1, 0, %g1
+ sethi %hi(solaris_sys_table), %l7
+ brz,pn %g1, solaris_sucks
+ mov %i0, %o0
+ sll %g1, 2, %l4
+ cmp %l0, 1
+ bne,pn %icc, solaris_reg
+1: mov %i1, %o1
+ lduw [%l7 + %l4], %l7
+ mov %i2, %o2
+ ldx [%g6 + AOFF_task_flags], %l5
+! st %g0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_FPRS]
+ cmp %l7, NR_SYSCALLS
+ bleu,a,pn %xcc, linux_syscall_for_solaris
+ sethi %hi(sys_call_table32), %l6
+ andcc %l7, 1, %g0
+ bne,a,pn %icc, 10f
+ add %sp, STACK_BIAS + REGWIN_SZ, %o0
+10: mov %i3, %o3
+ mov %i4, %o4
+ andn %l7, 3, %l7
+ andcc %l5, 0x20, %g0
+ bne,pn %icc, solaris_syscall_trace
+ mov %i0, %l5
+2: call %l7
+ mov %i5, %o5
+ret_from_solaris:
+#ifdef DEBUG_SOLARIS
+ call exit_printk
+ mov %o0, %l0
+ mov %l0, %o0
+#endif
+ stx %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
+ ldx [%g6 + AOFF_task_flags], %l6
+ sra %o0, 0, %o0
+ mov %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2
+ ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE], %g3
+ cmp %o0, -ENOIOCTLCMD
+ sllx %g2, 32, %g2
+ bgeu,pn %xcc, 1f
+ andcc %l6, 0x20, %l6
+
+ /* System call success, clear Carry condition code. */
+ andn %g3, %g2, %g3
+ stx %g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE]
+ bne,pn %icc, solaris_syscall_trace2
+ ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %l1 ! pc = npc
+ add %l1, 0x4, %l2 !npc = npc+4
+ stx %l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC]
+ clr %l6
+ call rtrap
+ stx %l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC]
+1:
+ /* System call failure, set Carry condition code.
+ * Also, get abs(errno) to return to the process.
+ */
+ sub %g0, %o0, %o0
+ or %g3, %g2, %g3
+ cmp %o0, ERANGE /* 0-ERANGE are identity mapped */
+ bleu,pt %icc, 1f
+ cmp %o0, EMEDIUMTYPE
+ bgu,pn %icc, 1f
+ sethi %hi(solaris_err_table), %l6
+ sll %o0, 2, %o0
+ or %l6, %lo(solaris_err_table), %l6
+ ldsw [%l6 + %o0], %o0
+1: stx %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
+ mov 1, %l6
+ stx %g3, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TSTATE]
+ bne,pn %icc, solaris_syscall_trace2
+ ldx [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC], %l1 ! pc = npc
+ add %l1, 0x4, %l2 !npc = npc+4
+
+ stx %l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC]
+ call rtrap
+ stx %l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC]
+solaris_syscall_trace2:
+ call syscall_trace
+ add %l1, 0x4, %l2 /* npc = npc+4 */
+ stx %l1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TPC]
+ call rtrap
+ stx %l2, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_TNPC]
+
+ /* This one is tricky, so that's why we do it in assembly */
+ .globl solaris_sigsuspend
+solaris_sigsuspend:
+ call do_sol_sigsuspend
+ nop
+ brlz,pn %o0, ret_from_solaris
+ nop
+ call sys_sigsuspend
+ stx %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I0]
+
+ .globl solaris_getpid
+solaris_getpid:
+ call sys_getppid /* This is tricky, so don't do it in assembly */
+ nop
+ stx %o0, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1]
+ b,pt %xcc, ret_from_solaris
+ lduw [%g6 + AOFF_task_pid], %o0
+
+ .globl solaris_getuid
+solaris_getuid:
+ lduh [%g6 + AOFF_task_euid], %o1
+ lduh [%g6 + AOFF_task_uid], %o0
+ b,pt %xcc, ret_from_solaris
+ stx %o1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1]
+
+ .globl solaris_getgid
+solaris_getgid:
+ lduh [%g6 + AOFF_task_egid], %o1
+ lduh [%g6 + AOFF_task_gid], %o0
+ b,pt %xcc, ret_from_solaris
+ stx %o1, [%sp + STACK_BIAS + REGWIN_SZ + PT_V9_I1]
+
+ .globl solaris_unimplemented
+solaris_unimplemented:
+ call do_sol_unimplemented
+ add %sp, STACK_BIAS + REGWIN_SZ, %o0
+ ba,pt %xcc, ret_from_solaris
+ nop
+
+ .section __ex_table,#alloc
+ .align 4
+ .word exen, exenf
+
diff --git a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c
new file mode 100644
index 000000000..9d0905adc
--- /dev/null
+++ b/arch/sparc64/solaris/fs.c
@@ -0,0 +1,711 @@
+/* $Id: fs.c,v 1.4 1997/09/04 15:46:26 jj Exp $
+ * fs.c: fs related syscall emulation for Solaris
+ *
+ * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/stat.h>
+#include <linux/smp_lock.h>
+#include <linux/limits.h>
+#include <linux/resource.h>
+
+#include <asm/uaccess.h>
+#include <asm/string.h>
+#include <asm/ptrace.h>
+
+#include "conv.h"
+
+extern char * getname32(u32 filename);
+#define putname32 putname
+
+#define R4_DEV(DEV) ((DEV & 0xff) | ((DEV & 0xff00) << 10))
+#define R4_MAJOR(DEV) (((DEV) >> 18) & 0x3fff)
+#define R4_MINOR(DEV) ((DEV) & 0x3ffff)
+#define R3_VERSION 1
+#define R4_VERSION 2
+
+typedef struct {
+ s32 tv_sec;
+ s32 tv_nsec;
+} timestruct_t;
+
+struct sol_stat {
+ u32 st_dev;
+ s32 st_pad1[3]; /* network id */
+ u32 st_ino;
+ u32 st_mode;
+ u32 st_nlink;
+ u32 st_uid;
+ u32 st_gid;
+ u32 st_rdev;
+ s32 st_pad2[2];
+ s32 st_size;
+ s32 st_pad3; /* st_size, off_t expansion */
+ timestruct_t st_atime;
+ timestruct_t st_mtime;
+ timestruct_t st_ctime;
+ s32 st_blksize;
+ s32 st_blocks;
+ char st_fstype[16];
+ s32 st_pad4[8]; /* expansion area */
+};
+
+#define UFSMAGIC (((unsigned)'u'<<24)||((unsigned)'f'<<16)||((unsigned)'s'<<8))
+
+static inline int putstat(struct sol_stat *ubuf, struct stat *kbuf)
+{
+ if (put_user (R4_DEV(kbuf->st_dev), &ubuf->st_dev) ||
+ __put_user (kbuf->st_ino, &ubuf->st_ino) ||
+ __put_user (kbuf->st_mode, &ubuf->st_mode) ||
+ __put_user (kbuf->st_nlink, &ubuf->st_nlink) ||
+ __put_user (kbuf->st_uid, &ubuf->st_uid) ||
+ __put_user (kbuf->st_gid, &ubuf->st_gid) ||
+ __put_user (R4_DEV(kbuf->st_rdev), &ubuf->st_rdev) ||
+ __put_user (kbuf->st_size, &ubuf->st_size) ||
+ __put_user (kbuf->st_atime, &ubuf->st_atime.tv_sec) ||
+ __put_user (0, &ubuf->st_atime.tv_nsec) ||
+ __put_user (kbuf->st_mtime, &ubuf->st_mtime.tv_sec) ||
+ __put_user (0, &ubuf->st_mtime.tv_nsec) ||
+ __put_user (kbuf->st_ctime, &ubuf->st_ctime.tv_sec) ||
+ __put_user (0, &ubuf->st_ctime.tv_nsec) ||
+ __put_user (kbuf->st_blksize, &ubuf->st_blksize) ||
+ __put_user (kbuf->st_blocks, &ubuf->st_blocks) ||
+ __put_user (UFSMAGIC, (unsigned *)ubuf->st_fstype))
+ return -EFAULT;
+ return 0;
+}
+
+asmlinkage int solaris_stat(u32 filename, u32 statbuf)
+{
+ int ret;
+ struct stat s;
+ char *filenam;
+ unsigned long old_fs = get_fs();
+ int (*sys_newstat)(char *,struct stat *) =
+ (int (*)(char *,struct stat *))SYS(stat);
+
+ filenam = getname32 (filename);
+ ret = PTR_ERR(filenam);
+ if (!IS_ERR(filenam)) {
+ set_fs (KERNEL_DS);
+ ret = sys_newstat(filenam, &s);
+ set_fs (old_fs);
+ putname32 (filenam);
+ if (putstat ((struct sol_stat *)A(statbuf), &s))
+ return -EFAULT;
+ }
+ return ret;
+}
+
+asmlinkage int solaris_xstat(int vers, u32 filename, u32 statbuf)
+{
+ /* Solaris doesn't bother with looking at vers, so we do neither */
+ return solaris_stat(filename, statbuf);
+}
+
+asmlinkage int solaris_lstat(u32 filename, u32 statbuf)
+{
+ int ret;
+ struct stat s;
+ char *filenam;
+ unsigned long old_fs = get_fs();
+ int (*sys_newlstat)(char *,struct stat *) =
+ (int (*)(char *,struct stat *))SYS(lstat);
+
+ filenam = getname32 (filename);
+ ret = PTR_ERR(filenam);
+ if (!IS_ERR(filenam)) {
+ set_fs (KERNEL_DS);
+ ret = sys_newlstat(filenam, &s);
+ set_fs (old_fs);
+ putname32 (filenam);
+ if (putstat ((struct sol_stat *)A(statbuf), &s))
+ return -EFAULT;
+ }
+ return ret;
+}
+
+asmlinkage int solaris_lxstat(int vers, u32 filename, u32 statbuf)
+{
+ return solaris_lstat(filename, statbuf);
+}
+
+asmlinkage int solaris_fstat(unsigned int fd, u32 statbuf)
+{
+ int ret;
+ struct stat s;
+ unsigned long old_fs = get_fs();
+ int (*sys_newfstat)(unsigned,struct stat *) =
+ (int (*)(unsigned,struct stat *))SYS(fstat);
+
+ set_fs (KERNEL_DS);
+ ret = sys_newfstat(fd, &s);
+ set_fs (old_fs);
+ if (putstat ((struct sol_stat *)A(statbuf), &s))
+ return -EFAULT;
+ return ret;
+}
+
+asmlinkage int solaris_fxstat(int vers, u32 fd, u32 statbuf)
+{
+ return solaris_fstat(fd, statbuf);
+}
+
+asmlinkage int solaris_mknod(u32 path, u32 mode, s32 dev)
+{
+ int (*sys_mknod)(const char *,int,dev_t) =
+ (int (*)(const char *,int,dev_t))SYS(mknod);
+ int major, minor;
+
+ if ((major = R4_MAJOR(dev)) > 255 ||
+ (minor = R4_MINOR(dev)) > 255) return -EINVAL;
+ return sys_mknod((const char *)A(path), mode, MKDEV(major,minor));
+}
+
+asmlinkage int solaris_xmknod(int vers, u32 path, u32 mode, s32 dev)
+{
+ return solaris_mknod(path, mode, dev);
+}
+
+/* This statfs thingie probably will go in the near future, but... */
+
+struct sol_statfs {
+ short f_type;
+ s32 f_bsize;
+ s32 f_frsize;
+ s32 f_blocks;
+ s32 f_bfree;
+ u32 f_files;
+ u32 f_ffree;
+ char f_fname[6];
+ char f_fpack[6];
+};
+
+asmlinkage int solaris_statfs(u32 path, u32 buf, int len, int fstype)
+{
+ int ret;
+ struct statfs s;
+ unsigned long old_fs = get_fs();
+ int (*sys_statfs)(const char *,struct statfs *) =
+ (int (*)(const char *,struct statfs *))SYS(statfs);
+ struct sol_statfs *ss = (struct sol_statfs *)A(buf);
+
+ if (len != sizeof(struct sol_statfs)) return -EINVAL;
+ if (!fstype) {
+ set_fs (KERNEL_DS);
+ ret = sys_statfs((const char *)A(path), &s);
+ set_fs (old_fs);
+ if (!ret) {
+ if (put_user (s.f_type, &ss->f_type) ||
+ __put_user (s.f_bsize, &ss->f_bsize) ||
+ __put_user (0, &ss->f_frsize) ||
+ __put_user (s.f_blocks, &ss->f_blocks) ||
+ __put_user (s.f_bfree, &ss->f_bfree) ||
+ __put_user (s.f_files, &ss->f_files) ||
+ __put_user (s.f_ffree, &ss->f_ffree) ||
+ __clear_user (&ss->f_fname, 12))
+ return -EFAULT;
+ }
+ return ret;
+ }
+/* Linux can't stat unmounted filesystems so we
+ * simply lie and claim 100MB of 1GB is free. Sorry.
+ */
+ if (put_user (fstype, &ss->f_type) ||
+ __put_user (1024, &ss->f_bsize) ||
+ __put_user (0, &ss->f_frsize) ||
+ __put_user (1024*1024, &ss->f_blocks) ||
+ __put_user (100*1024, &ss->f_bfree) ||
+ __put_user (60000, &ss->f_files) ||
+ __put_user (50000, &ss->f_ffree) ||
+ __clear_user (&ss->f_fname, 12))
+ return -EFAULT;
+ return 0;
+}
+
+asmlinkage int solaris_fstatfs(u32 fd, u32 buf, int len, int fstype)
+{
+ int ret;
+ struct statfs s;
+ unsigned long old_fs = get_fs();
+ int (*sys_fstatfs)(unsigned,struct statfs *) =
+ (int (*)(unsigned,struct statfs *))SYS(fstatfs);
+ struct sol_statfs *ss = (struct sol_statfs *)A(buf);
+
+ if (len != sizeof(struct sol_statfs)) return -EINVAL;
+ if (!fstype) {
+ set_fs (KERNEL_DS);
+ ret = sys_fstatfs(fd, &s);
+ set_fs (old_fs);
+ if (!ret) {
+ if (put_user (s.f_type, &ss->f_type) ||
+ __put_user (s.f_bsize, &ss->f_bsize) ||
+ __put_user (0, &ss->f_frsize) ||
+ __put_user (s.f_blocks, &ss->f_blocks) ||
+ __put_user (s.f_bfree, &ss->f_bfree) ||
+ __put_user (s.f_files, &ss->f_files) ||
+ __put_user (s.f_ffree, &ss->f_ffree) ||
+ __clear_user (&ss->f_fname, 12))
+ return -EFAULT;
+ }
+ return ret;
+ }
+ /* Otherwise fstatfs is the same as statfs */
+ return solaris_statfs(0, buf, len, fstype);
+}
+
+struct sol_statvfs {
+ u32 f_bsize;
+ u32 f_frsize;
+ u32 f_blocks;
+ u32 f_bfree;
+ u32 f_bavail;
+ u32 f_files;
+ u32 f_ffree;
+ u32 f_favail;
+ u32 f_fsid;
+ char f_basetype[16];
+ u32 f_flag;
+ u32 f_namemax;
+ char f_fstr[32];
+ u32 f_filler[16];
+};
+
+static int report_statvfs(struct inode *inode, u32 buf)
+{
+ struct statfs s;
+ unsigned long old_fs = get_fs();
+ int error;
+ struct sol_statvfs *ss = (struct sol_statvfs *)A(buf);
+
+ set_fs (KERNEL_DS);
+ error = inode->i_sb->s_op->statfs(inode->i_sb, &s, sizeof(struct statfs));
+ set_fs (old_fs);
+ if (!error) {
+ const char *p = inode->i_sb->s_type->name;
+ int i = 0;
+ int j = strlen (p);
+
+ if (j > 15) j = 15;
+ if (IS_RDONLY(inode)) i = 1;
+ if (IS_NOSUID(inode)) i |= 2;
+ if (put_user (s.f_bsize, &ss->f_bsize) ||
+ __put_user (0, &ss->f_frsize) ||
+ __put_user (s.f_blocks, &ss->f_blocks) ||
+ __put_user (s.f_bfree, &ss->f_bfree) ||
+ __put_user (s.f_bavail, &ss->f_bavail) ||
+ __put_user (s.f_files, &ss->f_files) ||
+ __put_user (s.f_ffree, &ss->f_ffree) ||
+ __put_user (s.f_ffree, &ss->f_favail) ||
+ __put_user (R4_DEV(inode->i_sb->s_dev), &ss->f_fsid) ||
+ __copy_to_user (ss->f_basetype,p,j) ||
+ __put_user (0, (char *)&ss->f_basetype[j]) ||
+ __put_user (s.f_namelen, &ss->f_namemax) ||
+ __put_user (i, &ss->f_flag) ||
+ __clear_user (&ss->f_fstr, 32))
+ return -EFAULT;
+ }
+ return error;
+}
+
+asmlinkage int solaris_statvfs(u32 path, u32 buf)
+{
+ struct dentry * dentry;
+ int error;
+
+ lock_kernel();
+ dentry = namei((const char *)A(path));
+ error = PTR_ERR(dentry);
+ if (!IS_ERR(dentry)) {
+ struct inode * inode = dentry->d_inode;
+
+ error = -ENOSYS;
+ if (inode->i_sb->s_op->statfs)
+ error = report_statvfs(inode, buf);
+ dput(dentry);
+ }
+ unlock_kernel();
+ return error;
+}
+
+asmlinkage int solaris_fstatvfs(unsigned int fd, u32 buf)
+{
+ struct inode * inode;
+ struct dentry * dentry;
+ struct file * file;
+ int error;
+
+ lock_kernel();
+ if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
+ error = -EBADF;
+ else if (!(dentry = file->f_dentry))
+ error = -ENOENT;
+ else if (!(inode = dentry->d_inode))
+ error = -ENOENT;
+ else if (!inode->i_sb)
+ error = -ENODEV;
+ else if (!inode->i_sb->s_op->statfs)
+ error = -ENOSYS;
+ else
+ error = report_statvfs(inode, buf);
+ unlock_kernel();
+ return error;
+}
+
+asmlinkage int solaris_open(u32 filename, int flags, u32 mode)
+{
+ int (*sys_open)(const char *,int,int) =
+ (int (*)(const char *,int,int))SYS(open);
+ int fl = flags & 0xf;
+
+ if (flags & 0x8050) fl |= O_SYNC;
+ if (flags & 0x80) fl |= O_NONBLOCK;
+ if (flags & 0x100) fl |= O_CREAT;
+ if (flags & 0x200) fl |= O_TRUNC;
+ if (flags & 0x400) fl |= O_EXCL;
+ if (flags & 0x800) fl |= O_NOCTTY;
+ return sys_open((const char *)A(filename), fl, mode);
+}
+
+#define SOL_F_SETLK 6
+#define SOL_F_SETLKW 7
+#define SOL_F_FREESP 11
+#define SOL_F_ISSTREAM 13
+#define SOL_F_GETLK 14
+#define SOL_F_PRIV 15
+#define SOL_F_NPRIV 16
+#define SOL_F_QUOTACTL 17
+#define SOL_F_BLOCKS 18
+#define SOL_F_BLKSIZE 19
+#define SOL_F_GETOWN 23
+#define SOL_F_SETOWN 24
+
+struct sol_flock {
+ short l_type;
+ short l_whence;
+ u32 l_start;
+ u32 l_len;
+ s32 l_sysid;
+ s32 l_pid;
+ s32 l_pad[4];
+};
+
+asmlinkage int solaris_fcntl(unsigned fd, unsigned cmd, u32 arg)
+{
+ int (*sys_fcntl)(unsigned,unsigned,unsigned long) =
+ (int (*)(unsigned,unsigned,unsigned long))SYS(fcntl);
+ int ret, flags;
+
+ switch (cmd) {
+ case F_DUPFD:
+ case F_GETFD:
+ case F_SETFD: return sys_fcntl(fd, cmd, (unsigned long)arg);
+ case F_GETFL:
+ flags = sys_fcntl(fd, cmd, 0);
+ ret = flags & 0xf;
+ if (flags & O_SYNC) ret |= 0x8050;
+ if (flags & O_NONBLOCK) ret |= 0x80;
+ return ret;
+ case F_SETFL:
+ flags = arg & 0xf;
+ if (arg & 0x8050) flags |= O_SYNC;
+ if (arg & 0x80) flags |= O_NONBLOCK;
+ return sys_fcntl(fd, cmd, (long)flags);
+ case SOL_F_GETLK:
+ case SOL_F_SETLK:
+ case SOL_F_SETLKW:
+ {
+ struct flock f;
+ unsigned long old_fs = get_fs();
+
+ switch (cmd) {
+ case SOL_F_GETLK: cmd = F_GETLK; break;
+ case SOL_F_SETLK: cmd = F_SETLK; break;
+ case SOL_F_SETLKW: cmd = F_SETLKW; break;
+ }
+
+ get_user_ret (f.l_type, &((struct sol_flock *)A(arg))->l_type, -EFAULT);
+ __get_user_ret (f.l_whence, &((struct sol_flock *)A(arg))->l_whence, -EFAULT);
+ __get_user_ret (f.l_start, &((struct sol_flock *)A(arg))->l_start, -EFAULT);
+ __get_user_ret (f.l_len, &((struct sol_flock *)A(arg))->l_len, -EFAULT);
+ __get_user_ret (f.l_pid, &((struct sol_flock *)A(arg))->l_sysid, -EFAULT);
+ set_fs(KERNEL_DS);
+ ret = sys_fcntl(fd, cmd, (unsigned long)&f);
+ set_fs(old_fs);
+ __put_user_ret (f.l_type, &((struct sol_flock *)A(arg))->l_type, -EFAULT);
+ __put_user_ret (f.l_whence, &((struct sol_flock *)A(arg))->l_whence, -EFAULT);
+ __put_user_ret (f.l_start, &((struct sol_flock *)A(arg))->l_start, -EFAULT);
+ __put_user_ret (f.l_len, &((struct sol_flock *)A(arg))->l_len, -EFAULT);
+ __put_user_ret (f.l_pid, &((struct sol_flock *)A(arg))->l_pid, -EFAULT);
+ __put_user_ret (0, &((struct sol_flock *)A(arg))->l_sysid, -EFAULT);
+ return ret;
+ }
+ }
+ return -EINVAL;
+}
+
+asmlinkage int solaris_ulimit(int cmd, int val)
+{
+ switch (cmd) {
+ case 1: /* UL_GETFSIZE - in 512B chunks */
+ return current->rlim[RLIMIT_FSIZE].rlim_cur >> 9;
+ case 2: /* UL_SETFSIZE */
+ if ((unsigned long)val > (LONG_MAX>>9)) return -ERANGE;
+ val <<= 9;
+ lock_kernel();
+ if (val > current->rlim[RLIMIT_FSIZE].rlim_max) {
+ if (!suser()) {
+ unlock_kernel();
+ return -EPERM;
+ }
+ current->rlim[RLIMIT_FSIZE].rlim_max = val;
+ }
+ current->rlim[RLIMIT_FSIZE].rlim_cur = val;
+ unlock_kernel();
+ return 0;
+ case 3: /* UL_GMEMLIM */
+ return current->rlim[RLIMIT_DATA].rlim_cur;
+ case 4: /* UL_GDESLIM */
+ return NR_OPEN;
+ }
+ return -EINVAL;
+}
+
+static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
+{
+ struct inode * inode;
+ struct iattr newattrs;
+ int error;
+
+ error = -ENOENT;
+ if (!(inode = dentry->d_inode)) {
+ printk("chown_common: NULL inode\n");
+ goto out;
+ }
+ error = -EROFS;
+ if (IS_RDONLY(inode))
+ goto out;
+ error = -EPERM;
+ if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
+ goto out;
+ if (user == (uid_t) -1)
+ user = inode->i_uid;
+ if (group == (gid_t) -1)
+ group = inode->i_gid;
+ newattrs.ia_mode = inode->i_mode;
+ newattrs.ia_uid = user;
+ newattrs.ia_gid = group;
+ newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
+ /*
+ * If the owner has been changed, remove the setuid bit
+ */
+ if (inode->i_mode & S_ISUID) {
+ newattrs.ia_mode &= ~S_ISUID;
+ newattrs.ia_valid |= ATTR_MODE;
+ }
+ /*
+ * If the group has been changed, remove the setgid bit
+ *
+ * Don't remove the setgid bit if no group execute bit.
+ * This is a file marked for mandatory locking.
+ */
+ if (((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))) {
+ newattrs.ia_mode &= ~S_ISGID;
+ newattrs.ia_valid |= ATTR_MODE;
+ }
+ if (inode->i_sb && inode->i_sb->dq_op) {
+ inode->i_sb->dq_op->initialize(inode, -1);
+ error = -EDQUOT;
+ if (inode->i_sb->dq_op->transfer(inode, &newattrs, 0))
+ goto out;
+ error = notify_change(inode, &newattrs);
+ if (error)
+ inode->i_sb->dq_op->transfer(inode, &newattrs, 1);
+ } else
+ error = notify_change(inode, &newattrs);
+out:
+ return error;
+}
+
+/* Linux chown works like Solaris lchown. Solaris chown does follow symlink */
+asmlinkage int solaris_chown(u32 filename, s32 user, s32 group)
+{
+ struct dentry * dentry;
+ int error;
+
+ lock_kernel();
+ dentry = namei((const char *)A(filename));
+
+ error = PTR_ERR(dentry);
+ if (!IS_ERR(dentry)) {
+ error = chown_common(dentry, user, group);
+ dput(dentry);
+ }
+ unlock_kernel();
+ return error;
+}
+
+/* At least at the time I'm writing this, Linux doesn't have ACLs, so we
+ just fake this */
+asmlinkage int solaris_acl(u32 filename, int cmd, int nentries, u32 aclbufp)
+{
+ return -ENOSYS;
+}
+
+asmlinkage int solaris_facl(unsigned int fd, int cmd, int nentries, u32 aclbufp)
+{
+ return -ENOSYS;
+}
+
+asmlinkage int solaris_pread(int fd, u32 buf, u32 nbyte, s32 offset)
+{
+ off_t temp;
+ int retval;
+ struct file * file;
+ long (*sys_read)(unsigned int, char *, unsigned long) =
+ (long (*)(unsigned int, char *, unsigned long))SYS(read);
+ long (*sys_lseek)(unsigned int, off_t, unsigned int) =
+ (long (*)(unsigned int, off_t, unsigned int))SYS(lseek);
+
+ lock_kernel();
+ retval = -EBADF;
+ if (fd >= NR_OPEN ||
+ !(file = current->files->fd[fd]))
+ goto bad;
+ temp = file->f_pos;
+ if (temp != offset) {
+ retval = sys_lseek(fd, offset, 0);
+ if (retval < 0) goto bad;
+ }
+ retval = sys_read(fd, (char *)A(buf), nbyte);
+ if (file->f_pos != temp) {
+ if (!retval)
+ retval = sys_lseek(fd, temp, 0);
+ else
+ sys_lseek(fd, temp, 0);
+ }
+bad:
+ unlock_kernel();
+ return retval;
+}
+
+asmlinkage int solaris_pwrite(int fd, u32 buf, u32 nbyte, s32 offset)
+{
+ off_t temp;
+ int retval;
+ struct file * file;
+ long (*sys_write)(unsigned int, char *, unsigned long) =
+ (long (*)(unsigned int, char *, unsigned long))SYS(read);
+ long (*sys_lseek)(unsigned int, off_t, unsigned int) =
+ (long (*)(unsigned int, off_t, unsigned int))SYS(lseek);
+
+ lock_kernel();
+ retval = -EBADF;
+ if (fd >= NR_OPEN ||
+ !(file = current->files->fd[fd]))
+ goto bad;
+ temp = file->f_pos;
+ if (temp != offset) {
+ retval = sys_lseek(fd, offset, 0);
+ if (retval < 0) goto bad;
+ }
+ retval = sys_write(fd, (char *)A(buf), nbyte);
+ if (file->f_pos != temp) {
+ if (!retval)
+ retval = sys_lseek(fd, temp, 0);
+ else
+ sys_lseek(fd, temp, 0);
+ }
+bad:
+ unlock_kernel();
+ return retval;
+}
+
+/* POSIX.1 names */
+#define _PC_LINK_MAX 1
+#define _PC_MAX_CANON 2
+#define _PC_MAX_INPUT 3
+#define _PC_NAME_MAX 4
+#define _PC_PATH_MAX 5
+#define _PC_PIPE_BUF 6
+#define _PC_NO_TRUNC 7
+#define _PC_VDISABLE 8
+#define _PC_CHOWN_RESTRICTED 9
+/* POSIX.4 names */
+#define _PC_ASYNC_IO 10
+#define _PC_PRIO_IO 11
+#define _PC_SYNC_IO 12
+#define _PC_LAST 12
+
+/* This is not a real and complete implementation yet, just to keep
+ * the easy Solaris binaries happy.
+ */
+asmlinkage int solaris_fpathconf(int fd, int name)
+{
+ int ret;
+
+ switch(name) {
+ case _PC_LINK_MAX:
+ ret = LINK_MAX;
+ break;
+ case _PC_MAX_CANON:
+ ret = MAX_CANON;
+ break;
+ case _PC_MAX_INPUT:
+ ret = MAX_INPUT;
+ break;
+ case _PC_NAME_MAX:
+ ret = NAME_MAX;
+ break;
+ case _PC_PATH_MAX:
+ ret = PATH_MAX;
+ break;
+ case _PC_PIPE_BUF:
+ ret = PIPE_BUF;
+ break;
+ case _PC_CHOWN_RESTRICTED:
+ ret = 1;
+ break;
+ case _PC_NO_TRUNC:
+ case _PC_VDISABLE:
+ ret = 0;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+asmlinkage int solaris_pathconf(u32 path, int name)
+{
+ return solaris_fpathconf(0, name);
+}
+
+/* solaris_llseek returns long long - quite difficult */
+asmlinkage long solaris_llseek(struct pt_regs *regs, u32 off_hi, u32 off_lo, int whence)
+{
+ int (*sys_llseek)(unsigned int, unsigned long, unsigned long, loff_t *, unsigned int) =
+ (int (*)(unsigned int, unsigned long, unsigned long, loff_t *, unsigned int))SYS(_llseek);
+ int ret;
+ unsigned long old_fs = get_fs();
+ loff_t retval;
+
+ set_fs(KERNEL_DS);
+ ret = sys_llseek((unsigned int)regs->u_regs[UREG_I0], off_hi, off_lo, &retval, whence);
+ set_fs(old_fs);
+ if (ret < 0) return ret;
+ regs->u_regs[UREG_I1] = (u32)retval;
+ return (retval >> 32);
+}
+
+/* Have to mask out all but lower 3 bits */
+asmlinkage int solaris_access(u32 filename, long mode)
+{
+ int (*sys_access)(const char *, int) =
+ (int (*)(const char *, int))SYS(access);
+
+ return sys_access((const char *)A(filename), mode & 7);
+}
diff --git a/arch/sparc64/solaris/ioctl.c b/arch/sparc64/solaris/ioctl.c
new file mode 100644
index 000000000..43b844caf
--- /dev/null
+++ b/arch/sparc64/solaris/ioctl.c
@@ -0,0 +1,316 @@
+/* $Id: ioctl.c,v 1.2 1997/09/04 00:59:22 davem Exp $
+ * ioctl.c: Solaris ioctl emulation.
+ *
+ * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ *
+ * Streams & timod emulation based on code
+ * Copyright (C) 1995, 1996 Mike Jagdis (jaggy@purplet.demon.co.uk)
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/ioctl.h>
+#include <linux/fs.h>
+
+#include <asm/uaccess.h>
+#include <asm/termios.h>
+
+#include "conv.h"
+
+extern char * getname32(u32 filename);
+#define putname32 putname
+
+extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd,
+ unsigned long arg);
+extern asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd,
+ u32 arg);
+asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg);
+
+/* termio* stuff {{{ */
+
+struct solaris_termios {
+ u32 c_iflag;
+ u32 c_oflag;
+ u32 c_cflag;
+ u32 c_lflag;
+ u8 c_cc[19];
+};
+
+struct solaris_termio {
+ u16 c_iflag;
+ u16 c_oflag;
+ u16 c_cflag;
+ u16 c_lflag;
+ s8 c_line;
+ u8 c_cc[8];
+};
+
+struct solaris_termiox {
+ u16 x_hflag;
+ u16 x_cflag;
+ u16 x_rflag[5];
+ u16 x_sflag;
+};
+
+static u32 solaris_to_linux_cflag(u32 cflag)
+{
+ cflag &= 0x7fdff000;
+ if (cflag & 0x200000) {
+ int baud = cflag & 0xf;
+ cflag &= ~0x20000f;
+ switch (baud) {
+ case 0: baud = B57600; break;
+ case 1: baud = B76800; break;
+ case 2: baud = B115200; break;
+ case 3: baud = B153600; break;
+ case 4: baud = B230400; break;
+ case 5: baud = B307200; break;
+ case 6: baud = B460800; break;
+ }
+ cflag |= CBAUDEX | baud;
+ }
+ return cflag;
+}
+
+static u32 linux_to_solaris_cflag(u32 cflag)
+{
+ cflag &= ~(CMSPAR | CIBAUD);
+ if (cflag & CBAUDEX) {
+ int baud = cflag & CBAUD;
+ cflag &= ~CBAUD;
+ switch (baud) {
+ case B57600: baud = 0; break;
+ case B76800: baud = 1; break;
+ case B115200: baud = 2; break;
+ case B153600: baud = 3; break;
+ case B230400: baud = 4; break;
+ case B307200: baud = 5; break;
+ case B460800: baud = 6; break;
+ case B614400: baud = 7; break;
+ case B921600: baud = 8; break;
+ /* case B1843200: baud = 9; break; */
+ }
+ cflag |= 0x200000 | baud;
+ }
+ return cflag;
+}
+
+static inline int linux_to_solaris_termio(unsigned int fd, unsigned int cmd, u32 arg)
+{
+ int ret;
+
+ ret = sys_ioctl(fd, cmd, A(arg));
+ if (!ret) {
+ u32 cflag;
+
+ if (__get_user (cflag, &((struct solaris_termio *)A(arg))->c_cflag))
+ return -EFAULT;
+ cflag = linux_to_solaris_cflag(cflag);
+ if (__put_user (cflag, &((struct solaris_termio *)A(arg))->c_cflag))
+ return -EFAULT;
+ }
+ return ret;
+}
+
+static int solaris_to_linux_termio(unsigned int fd, unsigned int cmd, u32 arg)
+{
+ int ret;
+ struct solaris_termio s;
+ unsigned long old_fs = get_fs();
+
+ if (copy_from_user (&s, (struct solaris_termio *)A(arg), sizeof(struct solaris_termio)))
+ return -EFAULT;
+ s.c_cflag = solaris_to_linux_cflag(s.c_cflag);
+ set_fs(KERNEL_DS);
+ ret = sys_ioctl(fd, cmd, (unsigned long)&s);
+ set_fs(old_fs);
+ return ret;
+}
+
+static inline int linux_to_solaris_termios(unsigned int fd, unsigned int cmd, u32 arg)
+{
+ int ret;
+ struct solaris_termios s;
+ unsigned long old_fs = get_fs();
+
+ set_fs(KERNEL_DS);
+ ret = sys_ioctl(fd, cmd, (unsigned long)&s);
+ set_fs(old_fs);
+ if (!ret) {
+ if (put_user (s.c_iflag, &((struct solaris_termios *)A(arg))->c_iflag) ||
+ __put_user (s.c_oflag, &((struct solaris_termios *)A(arg))->c_oflag) ||
+ __put_user (linux_to_solaris_cflag(s.c_cflag), &((struct solaris_termios *)A(arg))->c_cflag) ||
+ __put_user (s.c_lflag, &((struct solaris_termios *)A(arg))->c_lflag) ||
+ __copy_to_user (((struct solaris_termios *)A(arg))->c_cc, s.c_cc, 16) ||
+ __clear_user (((struct solaris_termios *)A(arg))->c_cc + 16, 2))
+ return -EFAULT;
+ }
+ return ret;
+}
+
+static int solaris_to_linux_termios(unsigned int fd, unsigned int cmd, u32 arg)
+{
+ int ret;
+ struct solaris_termios s;
+ unsigned long old_fs = get_fs();
+
+ set_fs(KERNEL_DS);
+ ret = sys_ioctl(fd, TCGETS, (unsigned long)&s);
+ set_fs(old_fs);
+ if (ret) return ret;
+ if (put_user (s.c_iflag, &((struct solaris_termios *)A(arg))->c_iflag) ||
+ __put_user (s.c_oflag, &((struct solaris_termios *)A(arg))->c_oflag) ||
+ __put_user (s.c_cflag, &((struct solaris_termios *)A(arg))->c_cflag) ||
+ __put_user (s.c_lflag, &((struct solaris_termios *)A(arg))->c_lflag) ||
+ __copy_from_user (s.c_cc, ((struct solaris_termios *)A(arg))->c_cc, 16))
+ return -EFAULT;
+ s.c_cflag = solaris_to_linux_cflag(s.c_cflag);
+ set_fs(KERNEL_DS);
+ ret = sys_ioctl(fd, cmd, (unsigned long)&s);
+ set_fs(old_fs);
+ return ret;
+}
+
+static inline int solaris_T(unsigned int fd, unsigned int cmd, u32 arg)
+{
+ switch (cmd & 0xff) {
+ case 1: /* TCGETA */
+ return linux_to_solaris_termio(fd, TCGETA, arg);
+ case 2: /* TCSETA */
+ return solaris_to_linux_termio(fd, TCSETA, arg);
+ case 3: /* TCSETAW */
+ return solaris_to_linux_termio(fd, TCSETAW, arg);
+ case 4: /* TCSETAF */
+ return solaris_to_linux_termio(fd, TCSETAF, arg);
+ case 5: /* TCSBRK */
+ return sys_ioctl(fd, TCSBRK, arg);
+ case 6: /* TCXONC */
+ return sys_ioctl(fd, TCXONC, arg);
+ case 7: /* TCFLSH */
+ return sys_ioctl(fd, TCFLSH, arg);
+ case 13: /* TCGETS */
+ return linux_to_solaris_termios(fd, TCGETS, arg);
+ case 14: /* TCSETS */
+ return solaris_to_linux_termios(fd, TCSETS, arg);
+ case 15: /* TCSETSW */
+ return solaris_to_linux_termios(fd, TCSETSW, arg);
+ case 16: /* TCSETSF */
+ return solaris_to_linux_termios(fd, TCSETSF, arg);
+ case 103: /* TIOCSWINSZ */
+ return sys_ioctl(fd, TIOCSWINSZ, arg);
+ case 104: /* TIOCGWINSZ */
+ return sys_ioctl(fd, TIOCGWINSZ, arg);
+ }
+ return -ENOSYS;
+}
+
+static inline int solaris_t(unsigned int fd, unsigned int cmd, u32 arg)
+{
+ switch (cmd & 0xff) {
+ case 20: /* TIOCGPGRP */
+ return sys_ioctl(fd, TIOCGPGRP, arg);
+ case 21: /* TIOCSPGRP */
+ return sys_ioctl(fd, TIOCSPGRP, arg);
+ }
+ return -ENOSYS;
+}
+
+/* }}} */
+
+/* A pseudo STREAMS support {{{ */
+
+struct strioctl {
+ int cmd, timeout, len;
+ u32 data;
+};
+
+static inline int solaris_S(unsigned int fd, unsigned int cmd, u32 arg)
+{
+ char *p;
+ int ret;
+ unsigned long old_fs;
+ struct strioctl si;
+
+ switch (cmd & 0xff) {
+ case 1: /* I_NREAD */
+ return -ENOSYS;
+ case 2: /* I_PUSH */
+ p = getname32 (arg);
+ if (IS_ERR (p))
+ return PTR_ERR(p);
+ putname32 (p);
+ return 0;
+ case 3: /* I_POP */
+ return 0;
+ case 5: /* I_FLUSH */
+ return 0;
+ case 8: /* I_STR */
+ if (copy_from_user (&si, (struct strioctl *)A(arg), sizeof(struct strioctl)))
+ return -EFAULT;
+ switch ((si.cmd >> 8) & 0xff) {
+ case 'T':
+ default:
+ return solaris_ioctl(fd, si.cmd, si.data);
+ }
+ case 9: /* I_SETSIG */
+ return sys_ioctl(fd, FIOSETOWN, current->pid);
+ case 10: /* I_GETSIG */
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ sys_ioctl(fd, FIOGETOWN, (unsigned long)&ret);
+ set_fs(old_fs);
+ if (ret == current->pid) return 0x3ff;
+ else return -EINVAL;
+ case 11: /* I_FIND */
+ p = getname32 (arg);
+ if (IS_ERR (p))
+ return PTR_ERR(p);
+ ret = !strcmp(p, "timod");
+ putname32 (p);
+ return ret;
+ }
+ return -ENOSYS;
+}
+/* }}} */
+
+asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
+{
+ struct file * filp;
+ int error = -EBADF;
+
+ lock_kernel();
+ if(fd >= NR_OPEN) goto out;
+
+ filp = current->files->fd[fd];
+ if(!filp) goto out;
+
+ if (!filp->f_op || !filp->f_op->ioctl) {
+ error = sys_ioctl (fd, cmd, (unsigned long)arg);
+ goto out;
+ }
+
+ error = -EFAULT;
+ switch ((cmd >> 8) & 0xff) {
+ case 'S': error = solaris_S(fd, cmd, arg); break;
+ case 'T': error = solaris_T(fd, cmd, arg); break;
+ case 't': error = solaris_t(fd, cmd, arg); break;
+ default:
+ error = -ENOSYS;
+ break;
+ }
+out:
+ if (error == -ENOSYS) {
+ unsigned char c = cmd>>8;
+
+ if (c < ' ' || c > 126) c = '.';
+ printk("solaris_ioctl: Unknown cmd fd(%d) cmd(%08x '%c') arg(%08x)\n",
+ (int)fd, (unsigned int)cmd, c, (unsigned int)arg);
+ error = -EINVAL;
+ }
+ unlock_kernel();
+ return error;
+}
diff --git a/arch/sparc64/solaris/ipc.c b/arch/sparc64/solaris/ipc.c
new file mode 100644
index 000000000..132028447
--- /dev/null
+++ b/arch/sparc64/solaris/ipc.c
@@ -0,0 +1,122 @@
+/* $Id: ipc.c,v 1.1 1997/09/03 12:29:29 jj Exp $
+ * ipc.c: Solaris IPC emulation
+ *
+ * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+#include <linux/types.h>
+#include <linux/smp_lock.h>
+#include <linux/shm.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+
+#include <asm/uaccess.h>
+#include <asm/string.h>
+#include <asm/ipc.h>
+
+#include "conv.h"
+
+struct solaris_ipc_perm {
+ s32 uid;
+ s32 gid;
+ s32 cuid;
+ s32 cgid;
+ u32 mode;
+ u32 seq;
+ int key;
+ s32 pad[4];
+};
+
+struct solaris_shmid_ds {
+ struct solaris_ipc_perm shm_perm;
+ int shm_segsz;
+ u32 shm_amp;
+ unsigned short shm_lkcnt;
+ char __padxx[2];
+ s32 shm_lpid;
+ s32 shm_cpid;
+ u32 shm_nattch;
+ u32 shm_cnattch;
+ s32 shm_atime;
+ s32 shm_pad1;
+ s32 shm_dtime;
+ s32 shm_pad2;
+ s32 shm_ctime;
+ s32 shm_pad3;
+ unsigned short shm_cv;
+ char shm_pad4[2];
+ u32 shm_sptas;
+ s32 shm_pad5[2];
+};
+
+asmlinkage long solaris_shmsys(int cmd, u32 arg1, u32 arg2, u32 arg3)
+{
+ int (*sys_ipc)(unsigned,int,int,unsigned long,void *,long) =
+ (int (*)(unsigned,int,int,unsigned long,void *,long))SYS(ipc);
+ unsigned long old_fs;
+ unsigned long raddr;
+ int ret;
+
+ switch (cmd) {
+ case 0: /* shmat */
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = sys_ipc(SHMAT, arg1, arg3 & ~0x4000, (unsigned long)&raddr, (void *)A(arg2), 0);
+ set_fs(old_fs);
+ if (ret >= 0) return (u32)raddr;
+ else return ret;
+ case 1: /* shmctl */
+ switch (arg2) {
+ case 3: /* SHM_LOCK */
+ case 4: /* SHM_UNLOCK */
+ return sys_ipc(SHMCTL, arg1, (arg2 == 3) ? SHM_LOCK : SHM_UNLOCK, 0, NULL, 0);
+ case 10: /* IPC_RMID */
+ return sys_ipc(SHMCTL, arg1, IPC_RMID, 0, NULL, 0);
+ case 11: /* IPC_SET */
+ {
+ struct shmid_ds s;
+
+ if (get_user (s.shm_perm.uid, &(((struct solaris_shmid_ds *)A(arg3))->shm_perm.uid)) ||
+ __get_user (s.shm_perm.gid, &(((struct solaris_shmid_ds *)A(arg3))->shm_perm.gid)) ||
+ __get_user (s.shm_perm.mode, &(((struct solaris_shmid_ds *)A(arg3))->shm_perm.mode)))
+ return -EFAULT;
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = sys_ipc(SHMCTL, arg1, IPC_SET, 0, &s, 0);
+ set_fs(old_fs);
+ return ret;
+ }
+ case 12: /* IPC_STAT */
+ {
+ struct shmid_ds s;
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = sys_ipc(SHMCTL, arg1, IPC_SET, 0, &s, 0);
+ set_fs(old_fs);
+ if (get_user (s.shm_perm.uid, &(((struct solaris_shmid_ds *)A(arg3))->shm_perm.uid)) ||
+ __get_user (s.shm_perm.gid, &(((struct solaris_shmid_ds *)A(arg3))->shm_perm.gid)) ||
+ __get_user (s.shm_perm.cuid, &(((struct solaris_shmid_ds *)A(arg3))->shm_perm.cuid)) ||
+ __get_user (s.shm_perm.cgid, &(((struct solaris_shmid_ds *)A(arg3))->shm_perm.cgid)) ||
+ __get_user (s.shm_perm.mode, &(((struct solaris_shmid_ds *)A(arg3))->shm_perm.mode)) ||
+ __get_user (s.shm_perm.seq, &(((struct solaris_shmid_ds *)A(arg3))->shm_perm.seq)) ||
+ __get_user (s.shm_perm.key, &(((struct solaris_shmid_ds *)A(arg3))->shm_perm.key)) ||
+ __get_user (s.shm_segsz, &(((struct solaris_shmid_ds *)A(arg3))->shm_segsz)) ||
+ __get_user (s.shm_lpid, &(((struct solaris_shmid_ds *)A(arg3))->shm_lpid)) ||
+ __get_user (s.shm_cpid, &(((struct solaris_shmid_ds *)A(arg3))->shm_cpid)) ||
+ __get_user (s.shm_nattch, &(((struct solaris_shmid_ds *)A(arg3))->shm_nattch)) ||
+ __get_user (s.shm_atime, &(((struct solaris_shmid_ds *)A(arg3))->shm_atime)) ||
+ __get_user (s.shm_dtime, &(((struct solaris_shmid_ds *)A(arg3))->shm_dtime)) ||
+ __get_user (s.shm_ctime, &(((struct solaris_shmid_ds *)A(arg3))->shm_ctime)))
+ return -EFAULT;
+ return ret;
+ }
+ default: return -EINVAL;
+ }
+ case 2: /* shmdt */
+ return sys_ipc(SHMDT, 0, 0, 0, (void *)A(arg1), 0);
+ case 3: /* shmget */
+ return sys_ipc(SHMGET, arg1, arg2, arg3, NULL, 0);
+ }
+ return -EINVAL;
+}
diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c
new file mode 100644
index 000000000..fdabd0e26
--- /dev/null
+++ b/arch/sparc64/solaris/misc.c
@@ -0,0 +1,463 @@
+/* $Id: misc.c,v 1.4 1997/09/04 14:57:31 jj Exp $
+ * misc.c: Miscelaneous syscall emulation for Solaris
+ *
+ * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/smp_lock.h>
+#include <linux/utsname.h>
+#include <linux/limits.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+
+#include <asm/uaccess.h>
+#include <asm/string.h>
+#include <asm/oplib.h>
+#include <asm/idprom.h>
+#include <asm/machines.h>
+
+#include "conv.h"
+
+/* Conversion from Linux to Solaris errnos. 0-34 are identity mapped.
+ Some Linux errnos (EPROCLIM, EDOTDOT, ERREMOTE, EUCLEAN, ENOTNAM,
+ ENAVAIL, EISNAM, EREMOTEIO, ENOMEDIUM, EMEDIUMTYPE) have no Solaris
+ equivalents. I return EINVAL in that case, which is very wrong. If
+ someone suggest a better value for them, you're welcomed.
+ On the other side, Solaris ECANCELED and ENOTSUP have no Linux equivalents,
+ but that doesn't matter here. --jj */
+int solaris_err_table[] = {
+/* 0 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+/* 10 */ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+/* 20 */ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+/* 30 */ 30, 31, 32, 33, 34, 22, 150, 149, 95, 96,
+/* 40 */ 97, 98, 99, 120, 121, 122, 123, 124, 125, 126,
+/* 50 */ 127, 128, 129, 130, 131, 132, 133, 134, 143, 144,
+/* 60 */ 145, 146, 90, 78, 147, 148, 93, 22, 94, 49,
+/* 70 */ 151, 66, 60, 62, 63, 35, 77, 36, 45, 46,
+/* 80 */ 64, 22, 67, 68, 69, 70, 71, 74, 22, 82,
+/* 90 */ 89, 92, 79, 81, 37, 38, 39, 40, 41, 42,
+/* 100 */ 43, 44, 50, 51, 52, 53, 54, 55, 56, 57,
+/* 110 */ 87, 61, 84, 65, 83, 80, 91, 22, 22, 22,
+/* 120 */ 22, 22, 88, 86, 85, 22, 22,
+};
+
+asmlinkage u32 solaris_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 off)
+{
+ u32 (*sunos_mmap)(u32,u32,u32,u32,u32,u32) =
+ (u32 (*)(u32,u32,u32,u32,u32,u32))SUNOS(71);
+ u32 ret;
+
+ ret = sunos_mmap(addr,len,prot,flags,fd,off);
+ /* sunos_mmap sets personality to PER_BSD */
+ current->personality = PER_SVR4;
+ return ret;
+}
+
+asmlinkage int solaris_brk(u32 brk)
+{
+ int (*sunos_brk)(u32) = (int (*)(u32))SUNOS(17);
+
+ return sunos_brk(brk);
+}
+
+#define set_utsfield(to, from, dotchop, countfrom) { \
+ char *p; \
+ int i, len = (countfrom) ? \
+ ((sizeof(to) > sizeof(from) ? \
+ sizeof(from) : sizeof(to))) : sizeof(to); \
+ copy_to_user_ret(to, from, len, -EFAULT); \
+ if (dotchop) \
+ for (p=from,i=0; *p && *p != '.' && --len; p++,i++); \
+ else \
+ i = len - 1; \
+ __put_user_ret('\0', (char *)(to+i), -EFAULT); \
+}
+
+struct sol_uname {
+ char sysname[9];
+ char nodename[9];
+ char release[9];
+ char version[9];
+ char machine[9];
+};
+
+struct sol_utsname {
+ char sysname[257];
+ char nodename[257];
+ char release[257];
+ char version[257];
+ char machine[257];
+};
+
+static char *machine(void)
+{
+ switch (sparc_cpu_model) {
+ case sun4: return "sun4";
+ case sun4c: return "sun4c";
+ case sun4e: return "sun4e";
+ case sun4m: return "sun4m";
+ case sun4d: return "sun4d";
+ case sun4u: return "sun4u";
+ default: return "sparc";
+ }
+}
+
+static char *platform(char *buffer)
+{
+ int i;
+ struct {
+ char *platform;
+ int id_machtype;
+ } platforms [] = {
+ { "sun4", (SM_SUN4 | SM_4_110) },
+ { "sun4", (SM_SUN4 | SM_4_260) },
+ { "sun4", (SM_SUN4 | SM_4_330) },
+ { "sun4", (SM_SUN4 | SM_4_470) },
+ { "SUNW,Sun_4_60", (SM_SUN4C | SM_4C_SS1) },
+ { "SUNW,Sun_4_40", (SM_SUN4C | SM_4C_IPC) },
+ { "SUNW,Sun_4_65", (SM_SUN4C | SM_4C_SS1PLUS) },
+ { "SUNW,Sun_4_20", (SM_SUN4C | SM_4C_SLC) },
+ { "SUNW,Sun_4_75", (SM_SUN4C | SM_4C_SS2) },
+ { "SUNW,Sun_4_25", (SM_SUN4C | SM_4C_ELC) },
+ { "SUNW,Sun_4_50", (SM_SUN4C | SM_4C_IPX) },
+ { "SUNW,Sun_4_600", (SM_SUN4M | SM_4M_SS60) },
+ { "SUNW,SPARCstation-5", (SM_SUN4M | SM_4M_SS50) },
+ { "SUNW,SPARCstation-20", (SM_SUN4M | SM_4M_SS40) }
+ };
+
+ *buffer = 0;
+ prom_getproperty(prom_root_node, "name", buffer, 256);
+ if (*buffer) {
+ char *p;
+
+ for (p = buffer; *p; p++)
+ if (*p == '/' || *p == ' ') *p = '_';
+ return buffer;
+ }
+ for (i = 0; i < sizeof (platforms)/sizeof (platforms[0]); i++)
+ if (platforms[i].id_machtype == idprom->id_machtype)
+ return platforms[i].platform;
+ return "sun4c";
+}
+
+static char *serial(char *buffer)
+{
+ int node = prom_getchild(prom_root_node);
+
+ node = prom_searchsiblings(node, "options");
+ *buffer = 0;
+ prom_getproperty(node, "system-board-serial#", buffer, 256);
+ if (!*buffer)
+ return "4512348717234";
+ else
+ return buffer;
+}
+
+asmlinkage int solaris_utssys(u32 buf, u32 flags, int which, u32 buf2)
+{
+ switch (which) {
+ case 0: /* old uname */
+ /* Lets cheat */
+ set_utsfield(((struct sol_uname *)A(buf))->sysname,
+ "SunOS", 1, 0);
+ set_utsfield(((struct sol_uname *)A(buf))->nodename,
+ system_utsname.nodename, 1, 1);
+ set_utsfield(((struct sol_uname *)A(buf))->release,
+ "2.6", 0, 0);
+ set_utsfield(((struct sol_uname *)A(buf))->version,
+ "Generic", 0, 0);
+ set_utsfield(((struct sol_uname *)A(buf))->machine,
+ machine(), 0, 0);
+ return 0;
+ case 2: /* ustat */
+ return -ENOSYS;
+ case 3: /* fusers */
+ return -ENOSYS;
+ default:
+ return -ENOSYS;
+ }
+}
+
+asmlinkage int solaris_utsname(u32 buf)
+{
+ /* Why should we not lie a bit? */
+ set_utsfield(((struct sol_utsname *)A(buf))->sysname,
+ "SunOS", 0, 0);
+ set_utsfield(((struct sol_utsname *)A(buf))->nodename,
+ system_utsname.nodename, 1, 1);
+ set_utsfield(((struct sol_utsname *)A(buf))->release,
+ "5.6", 0, 0);
+ set_utsfield(((struct sol_utsname *)A(buf))->version,
+ "Generic", 0, 0);
+ set_utsfield(((struct sol_utsname *)A(buf))->machine,
+ machine(), 0, 0);
+ return 0;
+}
+
+#define SI_SYSNAME 1 /* return name of operating system */
+#define SI_HOSTNAME 2 /* return name of node */
+#define SI_RELEASE 3 /* return release of operating system */
+#define SI_VERSION 4 /* return version field of utsname */
+#define SI_MACHINE 5 /* return kind of machine */
+#define SI_ARCHITECTURE 6 /* return instruction set arch */
+#define SI_HW_SERIAL 7 /* return hardware serial number */
+#define SI_HW_PROVIDER 8 /* return hardware manufacturer */
+#define SI_SRPC_DOMAIN 9 /* return secure RPC domain */
+#define SI_PLATFORM 513 /* return platform identifier */
+
+asmlinkage int solaris_sysinfo(int cmd, u32 buf, s32 count)
+{
+ char *p, *q, *r;
+ char buffer[256];
+ int len;
+
+ /* Again, we cheat :)) */
+ switch (cmd) {
+ case SI_SYSNAME: r = "SunOS"; break;
+ case SI_HOSTNAME:
+ r = buffer + 256;
+ for (p = system_utsname.nodename, q = buffer;
+ q < r && *p && *p != '.'; *q++ = *p++);
+ *q = 0;
+ r = buffer;
+ break;
+ case SI_RELEASE: r = "5.6"; break;
+ case SI_MACHINE: r = machine(); break;
+ case SI_ARCHITECTURE: r = "sparc"; break;
+ case SI_HW_PROVIDER: r = "Sun_Microsystems"; break;
+ case SI_HW_SERIAL: r = serial(buffer); break;
+ case SI_PLATFORM: r = platform(buffer); break;
+ case SI_SRPC_DOMAIN: r = ""; break;
+ case SI_VERSION: r = "Generic"; break;
+ default: return -EINVAL;
+ }
+ len = strlen(r) + 1;
+ if (count < len) {
+ copy_to_user_ret((char *)A(buf), r, count - 1, -EFAULT);
+ __put_user_ret(0, (char *)A(buf) + count - 1, -EFAULT);
+ } else
+ copy_to_user_ret((char *)A(buf), r, len, -EFAULT);
+ return len;
+}
+
+#define SOLARIS_CONFIG_NGROUPS 2
+#define SOLARIS_CONFIG_CHILD_MAX 3
+#define SOLARIS_CONFIG_OPEN_FILES 4
+#define SOLARIS_CONFIG_POSIX_VER 5
+#define SOLARIS_CONFIG_PAGESIZE 6
+#define SOLARIS_CONFIG_CLK_TCK 7
+#define SOLARIS_CONFIG_XOPEN_VER 8
+#define SOLARIS_CONFIG_PROF_TCK 10
+#define SOLARIS_CONFIG_NPROC_CONF 11
+#define SOLARIS_CONFIG_NPROC_ONLN 12
+#define SOLARIS_CONFIG_AIO_LISTIO_MAX 13
+#define SOLARIS_CONFIG_AIO_MAX 14
+#define SOLARIS_CONFIG_AIO_PRIO_DELTA_MAX 15
+#define SOLARIS_CONFIG_DELAYTIMER_MAX 16
+#define SOLARIS_CONFIG_MQ_OPEN_MAX 17
+#define SOLARIS_CONFIG_MQ_PRIO_MAX 18
+#define SOLARIS_CONFIG_RTSIG_MAX 19
+#define SOLARIS_CONFIG_SEM_NSEMS_MAX 20
+#define SOLARIS_CONFIG_SEM_VALUE_MAX 21
+#define SOLARIS_CONFIG_SIGQUEUE_MAX 22
+#define SOLARIS_CONFIG_SIGRT_MIN 23
+#define SOLARIS_CONFIG_SIGRT_MAX 24
+#define SOLARIS_CONFIG_TIMER_MAX 25
+#define SOLARIS_CONFIG_PHYS_PAGES 26
+#define SOLARIS_CONFIG_AVPHYS_PAGES 27
+
+asmlinkage int solaris_sysconf(int id)
+{
+ switch (id) {
+ case SOLARIS_CONFIG_NGROUPS: return NGROUPS_MAX;
+ case SOLARIS_CONFIG_CHILD_MAX: return CHILD_MAX;
+ case SOLARIS_CONFIG_OPEN_FILES: return OPEN_MAX;
+ case SOLARIS_CONFIG_POSIX_VER: return 199309;
+ case SOLARIS_CONFIG_PAGESIZE: return PAGE_SIZE;
+ case SOLARIS_CONFIG_XOPEN_VER: return 3;
+ case SOLARIS_CONFIG_CLK_TCK:
+ case SOLARIS_CONFIG_PROF_TCK:
+ return prom_getintdefault(
+ linux_cpus[smp_processor_id()].prom_node,
+ "clock-frequency", 167000000);
+#ifdef __SMP__
+ case SOLARIS_CONFIG_NPROC_CONF: return NCPUS;
+ case SOLARIS_CONFIG_NPROC_ONLN: return smp_num_cpus;
+#else
+ case SOLARIS_CONFIG_NPROC_CONF: return 1;
+ case SOLARIS_CONFIG_NPROC_ONLN: return 1;
+#endif
+ case SOLARIS_CONFIG_SIGRT_MIN: return 37;
+ case SOLARIS_CONFIG_SIGRT_MAX: return 44;
+ case SOLARIS_CONFIG_PHYS_PAGES:
+ case SOLARIS_CONFIG_AVPHYS_PAGES:
+ {
+ struct sysinfo s;
+
+ si_meminfo(&s);
+ if (id == SOLARIS_CONFIG_PHYS_PAGES)
+ return s.totalram >>= PAGE_SHIFT;
+ else
+ return s.freeram >>= PAGE_SHIFT;
+ }
+ /* XXX support these as well -jj */
+ case SOLARIS_CONFIG_AIO_LISTIO_MAX: return -EINVAL;
+ case SOLARIS_CONFIG_AIO_MAX: return -EINVAL;
+ case SOLARIS_CONFIG_AIO_PRIO_DELTA_MAX: return -EINVAL;
+ case SOLARIS_CONFIG_DELAYTIMER_MAX: return -EINVAL;
+ case SOLARIS_CONFIG_MQ_OPEN_MAX: return -EINVAL;
+ case SOLARIS_CONFIG_MQ_PRIO_MAX: return -EINVAL;
+ case SOLARIS_CONFIG_RTSIG_MAX: return -EINVAL;
+ case SOLARIS_CONFIG_SEM_NSEMS_MAX: return -EINVAL;
+ case SOLARIS_CONFIG_SEM_VALUE_MAX: return -EINVAL;
+ case SOLARIS_CONFIG_SIGQUEUE_MAX: return -EINVAL;
+ case SOLARIS_CONFIG_TIMER_MAX: return -EINVAL;
+ default: return -EINVAL;
+ }
+}
+
+asmlinkage int solaris_procids(int cmd, s32 pid, s32 pgid)
+{
+ int ret;
+
+ switch (cmd) {
+ case 0: /* getpgrp */
+ return current->pgrp;
+ case 1: /* setpgrp */
+ {
+ int (*sys_setpgid)(pid_t,pid_t) =
+ (int (*)(pid_t,pid_t))SYS(setpgid);
+
+ /* can anyone explain me the difference between
+ Solaris setpgrp and setsid? */
+ ret = sys_setpgid(0, 0);
+ if (ret) return ret;
+ current->tty = NULL;
+ return current->pgrp;
+ }
+ case 2: /* getsid */
+ {
+ int (*sys_getsid)(pid_t) = (int (*)(pid_t))SYS(getsid);
+ return sys_getsid(pid);
+ }
+ case 3: /* setsid */
+ {
+ int (*sys_setsid)(void) = (int (*)(void))SYS(setsid);
+ return sys_setsid();
+ }
+ case 4: /* getpgid */
+ {
+ int (*sys_getpgid)(pid_t) = (int (*)(pid_t))SYS(getpgid);
+ return sys_getpgid(pid);
+ }
+ case 5: /* setpgid */
+ {
+ int (*sys_setpgid)(pid_t,pid_t) =
+ (int (*)(pid_t,pid_t))SYS(setpgid);
+ return sys_setpgid(pid,pgid);
+ }
+ }
+ return -EINVAL;
+}
+
+asmlinkage int do_sol_unimplemented(struct pt_regs *regs)
+{
+ printk ("Unimplemented Solaris syscall %d %08x %08x %08x %08x\n",
+ (int)regs->u_regs[UREG_G1],
+ (int)regs->u_regs[UREG_I0],
+ (int)regs->u_regs[UREG_I1],
+ (int)regs->u_regs[UREG_I2],
+ (int)regs->u_regs[UREG_I3]);
+ return -ENOSYS;
+}
+
+asmlinkage void solaris_register(void)
+{
+ lock_kernel();
+ current->personality = PER_SVR4;
+ if (current->exec_domain && current->exec_domain->module)
+ __MOD_DEC_USE_COUNT(current->exec_domain->module);
+ current->exec_domain = lookup_exec_domain(current->personality);
+ if (current->exec_domain && current->exec_domain->module)
+ __MOD_INC_USE_COUNT(current->exec_domain->module);
+ unlock_kernel();
+}
+
+extern long solaris_to_linux_signals[], linux_to_solaris_signals[];
+
+struct exec_domain solaris_exec_domain = {
+ "Solaris",
+ (lcall7_func)NULL,
+ 1, 1, /* PER_SVR4 personality */
+ solaris_to_linux_signals,
+ linux_to_solaris_signals,
+#ifdef MODULE
+ &__this_module,
+#else
+ NULL,
+#endif
+ NULL
+};
+
+#ifdef MODULE
+
+MODULE_AUTHOR("Jakub Jelinek (jj@sunsite.mff.cuni.cz)");
+MODULE_DESCRIPTION("Solaris binary emulation module");
+
+#ifdef __sparc_v9__
+extern u32 tl0_solaris[8];
+#define update_ttable(x) \
+ tl0_solaris[3] = (((long)(x) - (long)tl0_solaris - 3) >> 2) | 0x40000000; \
+ __asm__ __volatile__ ("membar #StoreStore; flush %0" : : "r" (&tl0_solaris[3]))
+#else
+#endif
+
+extern u32 solaris_sparc_syscall[];
+extern u32 solaris_syscall[];
+extern int init_socksys(void);
+extern void cleanup_socksys(void);
+
+int init_module(void)
+{
+ int ret;
+ register_exec_domain(&solaris_exec_domain);
+ if ((ret = init_socksys())) {
+ unregister_exec_domain(&solaris_exec_domain);
+ return ret;
+ }
+ update_ttable(solaris_sparc_syscall);
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ update_ttable(solaris_syscall);
+ cleanup_socksys();
+ unregister_exec_domain(&solaris_exec_domain);
+}
+
+#else
+int init_solaris_emul(void)
+{
+ register_exec_domain(&solaris_exec_domain);
+ init_socksys();
+}
+#endif
+
+#ifdef DEBUG_SOLARIS
+void entry_printk(int sysno, struct pt_regs *regs)
+{
+ printk ("Entering %d\n", sysno);
+ printk ("%08x %08x %08x %08x\n", (int)regs->u_regs[UREG_I0],
+ (int)regs->u_regs[UREG_I1],
+ (int)regs->u_regs[UREG_I2],
+ (int)regs->u_regs[UREG_I3]);
+}
+
+void exit_printk(unsigned long ret)
+{
+ printk ("Returning %016lx\n", ret);
+}
+#endif
diff --git a/arch/sparc64/solaris/signal.c b/arch/sparc64/solaris/signal.c
new file mode 100644
index 000000000..6d3081c03
--- /dev/null
+++ b/arch/sparc64/solaris/signal.c
@@ -0,0 +1,419 @@
+/* $Id: signal.c,v 1.2 1997/09/03 12:29:19 jj Exp $
+ * signal.c: Signal emulation for Solaris
+ *
+ * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+#include <linux/types.h>
+#include <linux/smp_lock.h>
+
+#include <asm/uaccess.h>
+#include <asm/svr4.h>
+#include <asm/string.h>
+
+#include "conv.h"
+#include "signal.h"
+
+#define _S(nr) (1L<<((nr)-1))
+
+#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
+
+long linux_to_solaris_signals[] = {
+ 0,
+ SOLARIS_SIGHUP, SOLARIS_SIGINT,
+ SOLARIS_SIGQUIT, SOLARIS_SIGILL,
+ SOLARIS_SIGTRAP, SOLARIS_SIGIOT,
+ SOLARIS_SIGEMT, SOLARIS_SIGFPE,
+ SOLARIS_SIGKILL, SOLARIS_SIGBUS,
+ SOLARIS_SIGSEGV, SOLARIS_SIGSYS,
+ SOLARIS_SIGPIPE, SOLARIS_SIGALRM,
+ SOLARIS_SIGTERM, SOLARIS_SIGURG,
+ SOLARIS_SIGSTOP, SOLARIS_SIGTSTP,
+ SOLARIS_SIGCONT, SOLARIS_SIGCLD,
+ SOLARIS_SIGTTIN, SOLARIS_SIGTTOU,
+ SOLARIS_SIGPOLL, SOLARIS_SIGXCPU,
+ SOLARIS_SIGXFSZ, SOLARIS_SIGVTALRM,
+ SOLARIS_SIGPROF, SOLARIS_SIGWINCH,
+ SOLARIS_SIGUSR1, SOLARIS_SIGUSR1,
+ SOLARIS_SIGUSR2, -1,
+};
+
+long solaris_to_linux_signals[] = {
+ 0,
+ SIGHUP, SIGINT, SIGQUIT, SIGILL,
+ SIGTRAP, SIGIOT, SIGEMT, SIGFPE,
+ SIGKILL, SIGBUS, SIGSEGV, SIGSYS,
+ SIGPIPE, SIGALRM, SIGTERM, SIGUSR1,
+ SIGUSR2, SIGCHLD, -1, SIGWINCH,
+ SIGURG, SIGPOLL, SIGSTOP, SIGTSTP,
+ SIGCONT, SIGTTIN, SIGTTOU, SIGVTALRM,
+ SIGPROF, SIGXCPU, SIGXFSZ, -1,
+ -1, -1, -1, -1,
+ -1, -1, -1, -1,
+ -1, -1, -1, -1,
+};
+
+static inline long mapsig(long sig)
+{
+ if ((unsigned long)sig > SOLARIS_NSIGNALS)
+ return -EINVAL;
+ return solaris_to_linux_signals[sig];
+}
+
+asmlinkage int solaris_kill(int pid, int sig)
+{
+ int (*sys_kill)(int,int) =
+ (int (*)(int,int))SYS(kill);
+ int s = mapsig(sig);
+
+ if (s < 0) return s;
+ return sys_kill(pid, s);
+}
+
+static long sig_handler(int sig, u32 arg, int one_shot)
+{
+ struct sigaction sa, old;
+ int ret;
+ unsigned long old_fs = get_fs();
+ int (*sys_sigaction)(int,struct sigaction *,struct sigaction *) =
+ (int (*)(int,struct sigaction *,struct sigaction *))SYS(sigaction);
+
+ sa.sa_mask = 0L;
+ sa.sa_restorer = NULL;
+ sa.sa_handler = (__sighandler_t)A(arg);
+ sa.sa_flags = 0;
+ if (one_shot) sa.sa_flags = SA_ONESHOT | SA_NOMASK;
+ set_fs (KERNEL_DS);
+ ret = sys_sigaction(sig, &sa, &old);
+ set_fs (old_fs);
+ if (ret < 0) return ret;
+ return (u32)(long)old.sa_handler;
+}
+
+static inline long solaris_signal(int sig, u32 arg)
+{
+ return sig_handler (sig, arg, 1);
+}
+
+static long solaris_sigset(int sig, u32 arg)
+{
+ if (arg != 2) /* HOLD */ {
+ spin_lock_irq(&current->sigmask_lock);
+ current->blocked &= ~_S(sig);
+ spin_unlock_irq(&current->sigmask_lock);
+ return sig_handler (sig, arg, 0);
+ } else {
+ sigset_t n = _S(sig) & _BLOCKABLE;
+ spin_lock_irq(&current->sigmask_lock);
+ current->blocked |= n;
+ spin_unlock_irq(&current->sigmask_lock);
+ return 0;
+ }
+}
+
+static inline long solaris_sighold(int sig)
+{
+ return solaris_sigset(sig, 2);
+}
+
+static inline long solaris_sigrelse(int sig)
+{
+ spin_lock_irq(&current->sigmask_lock);
+ current->blocked &= ~_S(sig);
+ spin_unlock_irq(&current->sigmask_lock);
+ return 0;
+}
+
+static inline long solaris_sigignore(int sig)
+{
+ return sig_handler (sig, (u32)SIG_IGN, 0);
+}
+
+static inline long solaris_sigpause(int sig)
+{
+ printk ("Need to support solaris sigpause\n");
+ return -ENOSYS;
+}
+
+asmlinkage long solaris_sigfunc(int sig, u32 arg)
+{
+ int func = sig & ~0xff;
+
+ sig = mapsig(sig & 0xff);
+ if (sig < 0) return sig;
+ switch (func) {
+ case 0: return solaris_signal(sig, arg);
+ case 0x100: return solaris_sigset(sig, arg);
+ case 0x200: return solaris_sighold(sig);
+ case 0x400: return solaris_sigrelse(sig);
+ case 0x800: return solaris_sigignore(sig);
+ case 0x1000: return solaris_sigpause(sig);
+ }
+ return -EINVAL;
+}
+
+typedef struct {
+ u32 __sigbits[4];
+} sol_sigset_t;
+
+static inline int mapin(u32 *p, sigset_t *q)
+{
+ int i;
+ u32 x;
+ int sig;
+
+ *q = 0L;
+ x = p[0];
+ for (i = 1; i <= SOLARIS_NSIGNALS; i++) {
+ if (x & 1) {
+ sig = solaris_to_linux_signals[i];
+ if (sig == -1)
+ return -EINVAL;
+ *q |= 1L << (sig - 1);
+ }
+ x >>= 1;
+ if (i == 32)
+ x = p[1];
+ }
+ return 0;
+}
+
+static inline int mapout(sigset_t *q, u32 *p)
+{
+ int i;
+ sigset_t x;
+ int sig;
+
+ p[0] = 0;
+ p[1] = 0;
+ x = *q;
+ for (i = 1; i <= 32; i++, x >>= 1) {
+ if (x & 1) {
+ sig = linux_to_solaris_signals[i];
+ if (sig == -1)
+ return -EINVAL;
+ if (sig > 32)
+ p[1] |= 1L << (sig - 33);
+ else
+ p[0] |= 1L << (sig - 1);
+ }
+ }
+ return 0;
+
+}
+
+asmlinkage int solaris_sigprocmask(int how, u32 in, u32 out)
+{
+ sigset_t in_s, *ins, out_s, *outs;
+ unsigned long old_fs = get_fs();
+ int ret;
+ int (*sys_sigprocmask)(int,sigset_t *,sigset_t *) =
+ (int (*)(int,sigset_t *,sigset_t *))SYS(sigprocmask);
+
+ ins = NULL; outs = NULL;
+ if (in) {
+ u32 tmp[2];
+
+ if (copy_from_user (tmp, (sol_sigset_t *)A(in), 2*sizeof(u32)))
+ return -EFAULT;
+ ins = &in_s;
+ if (mapin (tmp, ins)) return -EINVAL;
+ }
+ if (out) outs = &out_s;
+ set_fs (KERNEL_DS);
+ ret = sys_sigprocmask((how == 3) ? SIG_SETMASK : how, ins, outs);
+ set_fs (old_fs);
+ if (ret) return ret;
+ if (out) {
+ u32 tmp[4];
+
+ tmp[2] = 0; tmp[3] = 0;
+ if (mapout (outs, tmp)) return -EINVAL;
+ if (copy_to_user((sol_sigset_t *)A(out), tmp, 4*sizeof(u32)))
+ return -EFAULT;
+ }
+ return 0;
+}
+
+asmlinkage long do_sol_sigsuspend(u32 mask)
+{
+ sigset_t s;
+ u32 tmp[2];
+
+ if (copy_from_user (tmp, (sol_sigset_t *)A(mask), 2*sizeof(u32)))
+ return -EFAULT;
+ if (mapin (tmp, &s)) return -EINVAL;
+ return (long)s;
+}
+
+struct sol_sigaction {
+ int sa_flags;
+ u32 sa_handler;
+ u32 sa_mask[4];
+ int sa_resv[2];
+};
+
+asmlinkage int solaris_sigaction(int sig, u32 act, u32 old)
+{
+ u32 tmp, tmp2[4];
+ struct sigaction s, s2;
+ int ret;
+ unsigned long old_fs = get_fs();
+ int (*sys_sigaction)(int,struct sigaction *,struct sigaction *) =
+ (int (*)(int,struct sigaction *,struct sigaction *))SYS(sigaction);
+
+ sig = mapsig(sig);
+ if (sig < 0) {
+ /* We cheat a little bit for Solaris only signals */
+ if (old && clear_user((struct sol_sigaction *)A(old), sizeof(struct sol_sigaction)))
+ return -EFAULT;
+ return 0;
+ }
+ if (act) {
+ if (get_user (tmp, &((struct sol_sigaction *)A(act))->sa_flags))
+ return -EFAULT;
+ s.sa_flags = 0;
+ if (tmp & SOLARIS_SA_ONSTACK) s.sa_flags |= SA_STACK;
+ if (tmp & SOLARIS_SA_RESTART) s.sa_flags |= SA_RESTART;
+ if (tmp & SOLARIS_SA_NODEFER) s.sa_flags |= SA_NOMASK;
+ if (tmp & SOLARIS_SA_RESETHAND) s.sa_flags |= SA_ONESHOT;
+ if (tmp & SOLARIS_SA_NOCLDSTOP) s.sa_flags |= SA_NOCLDSTOP;
+ if (get_user (tmp, &((struct sol_sigaction *)A(act))->sa_handler) ||
+ copy_from_user (tmp2, &((struct sol_sigaction *)A(act))->sa_mask, 2*sizeof(u32)))
+ return -EFAULT;
+ s.sa_handler = (__sighandler_t)A(tmp);
+ if (mapin (tmp2, &s.sa_mask)) return -EINVAL;
+ s.sa_restorer = 0;
+ }
+ set_fs(KERNEL_DS);
+ ret = sys_sigaction(sig, act ? &s : NULL, old ? &s2 : NULL);
+ set_fs(old_fs);
+ if (ret) return ret;
+ if (old) {
+ if (mapout (&s2.sa_mask, tmp2)) return -EINVAL;
+ tmp = 0; tmp2[2] = 0; tmp2[3] = 0;
+ if (s2.sa_flags & SA_STACK) tmp |= SOLARIS_SA_ONSTACK;
+ if (s2.sa_flags & SA_RESTART) tmp |= SOLARIS_SA_RESTART;
+ if (s2.sa_flags & SA_NOMASK) tmp |= SOLARIS_SA_NODEFER;
+ if (s2.sa_flags & SA_ONESHOT) tmp |= SOLARIS_SA_RESETHAND;
+ if (s2.sa_flags & SA_NOCLDSTOP) tmp |= SOLARIS_SA_NOCLDSTOP;
+ if (put_user (tmp, &((struct sol_sigaction *)A(old))->sa_flags) ||
+ __put_user ((u32)(long)s2.sa_handler, &((struct sol_sigaction *)A(old))->sa_handler) ||
+ copy_to_user (&((struct sol_sigaction *)A(old))->sa_mask, tmp2, 4*sizeof(u32)))
+ return -EFAULT;
+ }
+ return 0;
+}
+
+asmlinkage int solaris_sigpending(int which, u32 set)
+{
+ sigset_t s;
+ u32 tmp[4];
+ switch (which) {
+ case 1: /* sigpending */
+ lock_kernel();
+ s = current->blocked & current->signal;
+ unlock_kernel();
+ break;
+ case 2: /* sigfillset - I just set signals which have linux equivalents */
+ s = 0x7fffffff;
+ break;
+ default: return -EINVAL;
+ }
+ if (mapout (&s, tmp)) return -EINVAL;
+ tmp[2] = 0; tmp[3] = 0;
+ if (copy_to_user ((u32 *)A(set), tmp, sizeof(tmp)))
+ return -EFAULT;
+ return 0;
+}
+
+asmlinkage int solaris_wait(u32 stat_loc)
+{
+ int (*sys_wait4)(pid_t,unsigned int *, int, struct rusage *) =
+ (int (*)(pid_t,unsigned int *, int, struct rusage *))SYS(wait4);
+ int ret, status;
+
+ ret = sys_wait4(-1, (unsigned int *)A(stat_loc), WUNTRACED, NULL);
+ if (ret >= 0 && stat_loc) {
+ if (get_user (status, (unsigned int *)A(stat_loc)))
+ return -EFAULT;
+ if (((status - 1) & 0xffff) < 0xff)
+ status = linux_to_solaris_signals[status & 0x7f] & 0x7f;
+ else if ((status & 0xff) == 0x7f)
+ status = (linux_to_solaris_signals[(status >> 8) & 0xff] << 8) | 0x7f;
+ if (__put_user (status, (unsigned int *)A(stat_loc)))
+ return -EFAULT;
+ }
+ return ret;
+}
+
+asmlinkage int solaris_waitid(int idtype, s32 pid, u32 info, int options)
+{
+ int (*sys_wait4)(pid_t,unsigned int *, int, struct rusage *) =
+ (int (*)(pid_t,unsigned int *, int, struct rusage *))SYS(wait4);
+ int opts, status, ret;
+
+ switch (idtype) {
+ case 0: /* P_PID */ break;
+ case 1: /* P_PGID */ pid = -pid; break;
+ case 7: /* P_ALL */ pid = -1; break;
+ default: return -EINVAL;
+ }
+ opts = 0;
+ if (options & SOLARIS_WUNTRACED) opts |= WUNTRACED;
+ if (options & SOLARIS_WNOHANG) opts |= WNOHANG;
+ current->state = TASK_RUNNING;
+ ret = sys_wait4(pid, (unsigned int *)A(info), opts, NULL);
+ if (ret < 0) return ret;
+ if (info) {
+ struct sol_siginfo *s = (struct sol_siginfo *)A(info);
+
+ if (get_user (status, (unsigned int *)A(info))) return -EFAULT;
+ __put_user_ret (SOLARIS_SIGCLD, &s->si_signo, -EFAULT);
+ __put_user_ret (ret, &s->_data._proc._pid, -EFAULT);
+ switch (status & 0xff) {
+ case 0: ret = SOLARIS_CLD_EXITED;
+ status = (status >> 8) & 0xff;
+ break;
+ case 0x7f:
+ status = (status >> 8) & 0xff;
+ switch (status) {
+ case SIGSTOP:
+ case SIGTSTP: ret = SOLARIS_CLD_STOPPED;
+ default: ret = SOLARIS_CLD_EXITED;
+ }
+ status = linux_to_solaris_signals[status];
+ break;
+ default:
+ if (status & 0x80) ret = SOLARIS_CLD_DUMPED;
+ else ret = SOLARIS_CLD_KILLED;
+ status = linux_to_solaris_signals[status & 0x7f];
+ break;
+ }
+ __put_user_ret (ret, &s->si_code, -EFAULT);
+ __put_user_ret (status, &s->_data._proc._pdata._cld._status, -EFAULT);
+ }
+ return 0;
+}
+
+extern int svr4_setcontext(svr4_ucontext_t *c, struct pt_regs *regs);
+extern int svr4_getcontext(svr4_ucontext_t *c, struct pt_regs *regs);
+
+asmlinkage int solaris_context(struct pt_regs *regs)
+{
+ switch ((unsigned)regs->u_regs[UREG_I0]) {
+ case 0: /* getcontext */
+ return svr4_getcontext((svr4_ucontext_t *)(long)(u32)regs->u_regs[UREG_I1], regs);
+ case 1: /* setcontext */
+ return svr4_setcontext((svr4_ucontext_t *)(long)(u32)regs->u_regs[UREG_I1], regs);
+ default:
+ return -EINVAL;
+
+ }
+}
+
+asmlinkage int solaris_sigaltstack(u32 ss, u32 oss)
+{
+/* XXX Implement this soon */
+ return 0;
+}
diff --git a/arch/sparc64/solaris/signal.h b/arch/sparc64/solaris/signal.h
new file mode 100644
index 000000000..2e948c788
--- /dev/null
+++ b/arch/sparc64/solaris/signal.h
@@ -0,0 +1,109 @@
+/* $Id: signal.h,v 1.2 1997/09/03 12:29:21 jj Exp $
+ * signal.h: Signal emulation for Solaris
+ *
+ * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+#define SOLARIS_SIGHUP 1
+#define SOLARIS_SIGINT 2
+#define SOLARIS_SIGQUIT 3
+#define SOLARIS_SIGILL 4
+#define SOLARIS_SIGTRAP 5
+#define SOLARIS_SIGIOT 6
+#define SOLARIS_SIGEMT 7
+#define SOLARIS_SIGFPE 8
+#define SOLARIS_SIGKILL 9
+#define SOLARIS_SIGBUS 10
+#define SOLARIS_SIGSEGV 11
+#define SOLARIS_SIGSYS 12
+#define SOLARIS_SIGPIPE 13
+#define SOLARIS_SIGALRM 14
+#define SOLARIS_SIGTERM 15
+#define SOLARIS_SIGUSR1 16
+#define SOLARIS_SIGUSR2 17
+#define SOLARIS_SIGCLD 18
+#define SOLARIS_SIGPWR 19
+#define SOLARIS_SIGWINCH 20
+#define SOLARIS_SIGURG 21
+#define SOLARIS_SIGPOLL 22
+#define SOLARIS_SIGSTOP 23
+#define SOLARIS_SIGTSTP 24
+#define SOLARIS_SIGCONT 25
+#define SOLARIS_SIGTTIN 26
+#define SOLARIS_SIGTTOU 27
+#define SOLARIS_SIGVTALRM 28
+#define SOLARIS_SIGPROF 29
+#define SOLARIS_SIGXCPU 30
+#define SOLARIS_SIGXFSZ 31
+#define SOLARIS_SIGWAITING 32
+#define SOLARIS_SIGLWP 33
+#define SOLARIS_SIGFREEZE 34
+#define SOLARIS_SIGTHAW 35
+#define SOLARIS_SIGCANCEL 36
+#define SOLARIS_SIGRTMIN 37
+#define SOLARIS_SIGRTMAX 44
+#define SOLARIS_NSIGNALS 44
+
+
+#define SOLARIS_SA_ONSTACK 1
+#define SOLARIS_SA_RESETHAND 2
+#define SOLARIS_SA_RESTART 4
+#define SOLARIS_SA_SIGINFO 8
+#define SOLARIS_SA_NODEFER 16
+#define SOLARIS_SA_NOCLDWAIT 0x10000
+#define SOLARIS_SA_NOCLDSTOP 0x20000
+
+struct sol_siginfo {
+ int si_signo;
+ int si_code;
+ int si_errno;
+ union {
+ char pad[128-3*sizeof(int)];
+ struct {
+ s32 _pid;
+ union {
+ struct {
+ s32 _uid;
+ s32 _value;
+ } _kill;
+ struct {
+ s32 _utime;
+ int _status;
+ s32 _stime;
+ } _cld;
+ } _pdata;
+ } _proc;
+ struct { /* SIGSEGV, SIGBUS, SIGILL and SIGFPE */
+ u32 _addr;
+ int _trapno;
+ } _fault;
+ struct { /* SIGPOLL, SIGXFSZ */
+ int _fd;
+ s32 _band;
+ } _file;
+ } _data;
+};
+
+#define SOLARIS_WUNTRACED 0x04
+#define SOLARIS_WNOHANG 0x40
+#define SOLARIS_WEXITED 0x01
+#define SOLARIS_WTRAPPED 0x02
+#define SOLARIS_WSTOPPED WUNTRACED
+#define SOLARIS_WCONTINUED 0x08
+#define SOLARIS_WNOWAIT 0x80
+
+#define SOLARIS_TRAP_BRKPT 1
+#define SOLARIS_TRAP_TRACE 2
+#define SOLARIS_CLD_EXITED 1
+#define SOLARIS_CLD_KILLED 2
+#define SOLARIS_CLD_DUMPED 3
+#define SOLARIS_CLD_TRAPPED 4
+#define SOLARIS_CLD_STOPPED 5
+#define SOLARIS_CLD_CONTINUED 6
+#define SOLARIS_POLL_IN 1
+#define SOLARIS_POLL_OUT 2
+#define SOLARIS_POLL_MSG 3
+#define SOLARIS_POLL_ERR 4
+#define SOLARIS_POLL_PRI 5
+#define SOLARIS_POLL_HUP 6
+
diff --git a/arch/sparc64/solaris/socksys.c b/arch/sparc64/solaris/socksys.c
new file mode 100644
index 000000000..984b1bdb5
--- /dev/null
+++ b/arch/sparc64/solaris/socksys.c
@@ -0,0 +1,127 @@
+/* $Id: socksys.c,v 1.1 1997/09/03 12:29:27 jj Exp $
+ * socksys.c: /dev/inet/ stuff for Solaris emulation.
+ *
+ * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1995, 1996 Mike Jagdis (jaggy@purplet.demon.co.uk)
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/ioctl.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/poll.h>
+
+#include <asm/uaccess.h>
+#include <asm/termios.h>
+
+#include "conv.h"
+
+extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd,
+ unsigned long arg);
+
+static int af_inet_protocols[] = {
+IPPROTO_ICMP, IPPROTO_ICMP, IPPROTO_IGMP, IPPROTO_IPIP, IPPROTO_TCP,
+IPPROTO_EGP, IPPROTO_PUP, IPPROTO_UDP, IPPROTO_IDP, IPPROTO_RAW,
+0, 0, 0, 0, 0, 0,
+};
+
+static struct file_operations socksys_file_ops = {
+ NULL, /* lseek */
+ NULL, /* read */
+ NULL, /* write */
+ NULL, /* readdir */
+ NULL, /* poll */
+ NULL, /* ioctl */
+ NULL, /* mmap */
+ NULL, /* open */
+ NULL, /* release */
+};
+
+static int socksys_open(struct inode * inode, struct file * filp)
+{
+ int family, type, protocol, fd;
+ int (*sys_socket)(int,int,int) =
+ (int (*)(int,int,int))SUNOS(97);
+
+ family = ((MINOR(inode->i_rdev) >> 4) & 0xf);
+ switch (family) {
+ case AF_UNIX:
+ type = SOCK_STREAM;
+ protocol = 0;
+ break;
+ case AF_INET:
+ protocol = af_inet_protocols[MINOR(inode->i_rdev) & 0xf];
+ switch (protocol) {
+ case IPPROTO_TCP: type = SOCK_STREAM; break;
+ case IPPROTO_UDP: type = SOCK_DGRAM; break;
+ default: type = SOCK_RAW; break;
+ }
+ break;
+ default:
+ type = SOCK_RAW;
+ protocol = 0;
+ break;
+ }
+ fd = sys_socket(family, type, protocol);
+ if (fd < 0) return fd;
+ return 0;
+}
+
+static int socksys_release(struct inode * inode, struct file * filp)
+{
+ return 0;
+}
+
+static unsigned int socksys_poll(struct file * filp, poll_table * wait)
+{
+ return 0;
+}
+
+static struct file_operations socksys_fops = {
+ NULL, /* lseek */
+ NULL, /* read */
+ NULL, /* write */
+ NULL, /* readdir */
+ NULL, /* poll */
+ NULL, /* ioctl */
+ NULL, /* mmap */
+ socksys_open, /* open */
+ socksys_release,/* release */
+};
+
+__initfunc(int
+init_socksys(void))
+{
+ int ret;
+ int (*sys_socket)(int,int,int) =
+ (int (*)(int,int,int))SUNOS(97);
+ int (*sys_close)(unsigned int) =
+ (int (*)(unsigned int))SYS(close);
+
+ ret = register_chrdev (30, "socksys", &socksys_fops);
+ if (ret < 0) {
+ printk ("Couldn't register socksys character device\n");
+ return ret;
+ }
+ ret = sys_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (ret < 0) {
+ printk ("Couldn't create socket\n");
+ return ret;
+ }
+ socksys_file_ops = *current->files->fd[ret]->f_op;
+ sys_close(ret);
+ socksys_file_ops.poll = socksys_poll;
+ socksys_file_ops.release = socksys_release;
+ return 0;
+}
+
+void
+cleanup_socksys(void)
+{
+ if (unregister_chrdev (30, "socksys"))
+ printk ("Couldn't unregister socksys character device\n");
+}
diff --git a/arch/sparc64/solaris/systbl.S b/arch/sparc64/solaris/systbl.S
new file mode 100644
index 000000000..c425fb721
--- /dev/null
+++ b/arch/sparc64/solaris/systbl.S
@@ -0,0 +1,289 @@
+/* $Id: systbl.S,v 1.5 1997/09/04 15:46:24 jj Exp $
+ * systbl.S: System call entry point table for Solaris compatibility.
+ *
+ * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
+ */
+
+#include <asm/unistd.h>
+
+/* Fall back to sys_call_table32 entry */
+#define CHAIN(name) __NR_##name
+
+/* Pass pt_regs pointer as first argument */
+#define REGS(name) name+1
+
+/* Hack till all be implemented */
+#define solaris_getmsg solaris_unimplemented
+#define solaris_getpmsg solaris_unimplemented
+#define solaris_hrtsys solaris_unimplemented
+#define solaris_msgsys solaris_unimplemented
+#define solaris_putmsg solaris_unimplemented
+#define solaris_putpmsg solaris_unimplemented
+#define solaris_semsys solaris_unimplemented
+
+ .data
+ .align 1024
+ .globl solaris_sys_table
+solaris_sys_table:
+ .word solaris_unimplemented /* nosys 0 */
+ .word CHAIN(exit) /* exit d 1 */
+ .word CHAIN(fork) /* fork 2 */
+ .word CHAIN(read) /* read dpd 3 */
+ .word CHAIN(write) /* write dpd 4 */
+ .word solaris_open /* open soo 5 */
+ .word CHAIN(close) /* close d 6 */
+ .word solaris_wait /* wait xxx 7 */
+ .word CHAIN(creat) /* creat so 8 */
+ .word CHAIN(link) /* link ss 9 */
+ .word CHAIN(unlink) /* unlink s 10 */
+ .word solaris_unimplemented /* exec sxx 11 */
+ .word CHAIN(chdir) /* chdir s 12 */
+ .word CHAIN(time) /* time 13 */
+ .word solaris_mknod /* mknod sox 14 */
+ .word CHAIN(chmod) /* chmod so 15 */
+ .word solaris_chown /* chown sdd 16 */
+ .word solaris_brk /* brk/break x 17 */
+ .word solaris_stat /* stat sp 18 */
+ .word CHAIN(lseek) /* seek/lseek ddd 19 */
+ .word solaris_getpid /* getpid 20 */
+ .word solaris_unimplemented /* mount 21 */
+ .word CHAIN(umount) /* umount s 22 */
+ .word CHAIN(setuid) /* setuid d 23 */
+ .word solaris_getuid /* getuid 24 */
+ .word CHAIN(stime) /* stime d 25 */
+#if 0
+ .word solaris_ptrace /* ptrace xdxx 26 */
+#else
+ .word CHAIN(ptrace) /* ptrace xdxx 26 */
+#endif
+ .word CHAIN(alarm) /* alarm d 27 */
+ .word solaris_fstat /* fstat dp 28 */
+ .word CHAIN(pause) /* pause 29 */
+ .word CHAIN(utime) /* utime xx 30 */
+ .word solaris_unimplemented /* stty 31 */
+ .word solaris_unimplemented /* gtty 32 */
+ .word solaris_access /* access so 33 */
+ .word CHAIN(nice) /* nice d 34 */
+ .word solaris_statfs /* statfs spdd 35 */
+ .word CHAIN(sync) /* sync 36 */
+ .word solaris_kill /* kill dd 37 */
+ .word solaris_fstatfs /* fstatfs dpdd 38 */
+ .word solaris_procids /* pgrpsys ddd 39 */
+ .word solaris_unimplemented /* xenix 40 */
+ .word CHAIN(dup) /* dup d 41 */
+ .word CHAIN(pipe) /* pipe 42 */
+ .word CHAIN(times) /* times p 43 */
+ .word CHAIN(profil) /* prof xxxx 44 */
+ .word solaris_unimplemented /* lock/plock 45 */
+ .word CHAIN(setgid) /* setgid d 46 */
+ .word solaris_getgid /* getgid 47 */
+ .word solaris_sigfunc /* sigfunc xx 48 */
+ .word REGS(solaris_msgsys) /* msgsys dxddd 49 */
+ .word solaris_unimplemented /* syssun/3b 50 */
+ .word CHAIN(acct) /* acct/sysacct x 51 */
+ .word solaris_shmsys /* shmsys ddxo 52 */
+ .word REGS(solaris_semsys) /* semsys dddx 53 */
+ .word solaris_ioctl /* ioctl dxx 54 */
+ .word solaris_unimplemented /* uadmin xxx 55 */
+ .word solaris_unimplemented /* reserved:exch 56 */
+ .word solaris_utssys /* utssys x 57 */
+ .word CHAIN(fsync) /* fsync d 58 */
+ .word CHAIN(execve) /* execv spp 59 */
+ .word CHAIN(umask) /* umask o 60 */
+ .word CHAIN(chroot) /* chroot s 61 */
+ .word solaris_fcntl /* fcntl dxx 62 */
+ .word solaris_ulimit /* ulimit xx 63 */
+ .word solaris_unimplemented /* ? 64 */
+ .word solaris_unimplemented /* ? 65 */
+ .word solaris_unimplemented /* ? 66 */
+ .word solaris_unimplemented /* ? 67 */
+ .word solaris_unimplemented /* ? 68 */
+ .word solaris_unimplemented /* ? 69 */
+ .word solaris_unimplemented /* advfs 70 */
+ .word solaris_unimplemented /* unadvfs 71 */
+ .word solaris_unimplemented /* rmount 72 */
+ .word solaris_unimplemented /* rumount 73 */
+ .word solaris_unimplemented /* rfstart 74 */
+ .word solaris_unimplemented /* ? 75 */
+ .word solaris_unimplemented /* rdebug 76 */
+ .word solaris_unimplemented /* rfstop 77 */
+ .word solaris_unimplemented /* rfsys 78 */
+ .word CHAIN(rmdir) /* rmdir s 79 */
+ .word CHAIN(mkdir) /* mkdir so 80 */
+ .word CHAIN(getdents) /* getdents dxd 81 */
+ .word solaris_unimplemented /* libattach 82 */
+ .word solaris_unimplemented /* libdetach 83 */
+ .word CHAIN(sysfs) /* sysfs dxx 84 */
+ .word REGS(solaris_getmsg) /* getmsg dxxx 85 */
+ .word REGS(solaris_putmsg) /* putmsg dxxd 86 */
+ .word CHAIN(poll) /* poll xdd 87 */
+ .word solaris_lstat /* lstat sp 88 */
+ .word CHAIN(symlink) /* symlink ss 89 */
+ .word CHAIN(readlink) /* readlink spd 90 */
+ .word CHAIN(setgroups) /* setgroups dp 91 */
+ .word CHAIN(getgroups) /* getgroups dp 92 */
+ .word CHAIN(fchmod) /* fchmod do 93 */
+ .word CHAIN(fchown) /* fchown ddd 94 */
+ .word solaris_sigprocmask /* sigprocmask dxx 95 */
+ .word solaris_sigsuspend /* sigsuspend x 96 */
+ .word solaris_sigaltstack /* sigaltstack xx 97 */
+ .word solaris_sigaction /* sigaction dxx 98 */
+ .word solaris_sigpending /* sigpending dd 99 */
+ .word REGS(solaris_context) /* context 100 */
+ .word solaris_unimplemented /* evsys 101 */
+ .word solaris_unimplemented /* evtrapret 102 */
+ .word solaris_statvfs /* statvfs sp 103 */
+ .word solaris_fstatvfs /* fstatvfs dp 104 */
+ .word solaris_unimplemented /* unknown 105 */
+ .word solaris_unimplemented /* nfssys 106 */
+ .word solaris_waitid /* waitid ddxd 107 */
+ .word solaris_unimplemented /* sigsendsys ddd 108 */
+ .word REGS(solaris_hrtsys) /* hrtsys xxx 109 */
+ .word solaris_unimplemented /* acancel dxd 110 */
+ .word solaris_unimplemented /* async 111 */
+ .word solaris_unimplemented /* priocntlsys 112 */
+ .word solaris_pathconf /* pathconf sd 113 */
+ .word solaris_unimplemented /* mincore xdx 114 */
+ .word solaris_mmap /* mmap xxxxdx 115 */
+ .word CHAIN(mprotect) /* mprotect xdx 116 */
+ .word CHAIN(munmap) /* munmap xd 117 */
+ .word solaris_fpathconf /* fpathconf dd 118 */
+ .word CHAIN(fork) /* fork 119 */
+ .word solaris_unimplemented /* fchdir d 120 */
+ .word CHAIN(readv) /* readv dxd 121 */
+ .word CHAIN(writev) /* writev dxd 122 */
+ .word solaris_xstat /* xstat dsx 123 */
+ .word solaris_lxstat /* lxstat dsx 124 */
+ .word solaris_fxstat /* fxstat ddx 125 */
+ .word solaris_xmknod /* xmknod dsox 126 */
+ .word solaris_unimplemented /* syslocal d 127 */
+ .word solaris_unimplemented /* setrlimit 128 */
+ .word solaris_unimplemented /* getrlimit 129 */
+ .word CHAIN(chown) /* lchown sdd 130 */
+ .word solaris_unimplemented /* memcntl 131 */
+ .word solaris_getpmsg /* getpmsg dxxxx 132 */
+ .word solaris_putpmsg /* putpmsg dxxdd 133 */
+ .word CHAIN(rename) /* rename ss 134 */
+ .word solaris_utsname /* uname x 135 */
+ .word solaris_unimplemented /* setegid 136 */
+ .word solaris_sysconf /* sysconfig d 137 */
+ .word solaris_unimplemented /* adjtime 138 */
+ .word solaris_sysinfo /* systeminfo dsd 139 */
+ .word solaris_unimplemented /* ? 140 */
+ .word solaris_unimplemented /* seteuid 141 */
+ .word solaris_unimplemented /* ? 142 */
+ .word solaris_unimplemented /* ? 143 */
+ .word solaris_unimplemented /* secsys dx 144 */
+ .word solaris_unimplemented /* filepriv sdxd 145 */
+ .word solaris_unimplemented /* procpriv dxd 146 */
+ .word solaris_unimplemented /* devstat sdx 147 */
+ .word solaris_unimplemented /* aclipc ddddx 148 */
+ .word solaris_unimplemented /* fdevstat ddx 149 */
+ .word solaris_unimplemented /* flvlfile ddx 150 */
+ .word solaris_unimplemented /* lvlfile sdx 151 */
+ .word solaris_unimplemented /* ? 152 */
+ .word solaris_unimplemented /* fchroot d 153 */
+ .word solaris_unimplemented /* lvlproc dx 154 */
+ .word solaris_unimplemented /* ? 155 */
+ .word CHAIN(gettimeofday) /* gettimeofday xx 156 */
+ .word CHAIN(getitimer) /* getitimer dx 157 */
+ .word CHAIN(setitimer) /* setitimer dxx 158 */
+ .word solaris_unimplemented /* lwp-xxx 159 */
+ .word solaris_unimplemented /* lwp-xxx 160 */
+ .word solaris_unimplemented /* lwp-xxx 161 */
+ .word solaris_unimplemented /* lwp-xxx 162 */
+ .word solaris_unimplemented /* lwp-xxx 163 */
+ .word solaris_unimplemented /* lwp-xxx 164 */
+ .word solaris_unimplemented /* lwp-xxx 165 */
+ .word solaris_unimplemented /* lwp-xxx 166 */
+ .word solaris_unimplemented /* lwp-xxx 167 */
+ .word solaris_unimplemented /* lwp-xxx 168 */
+ .word solaris_unimplemented /* lwp-xxx 169 */
+ .word solaris_unimplemented /* lwp-xxx 170 */
+ .word solaris_unimplemented /* lwp-xxx 171 */
+ .word solaris_unimplemented /* lwp-xxx 172 */
+ .word solaris_pread /* pread dpdd 173 */
+ .word solaris_pwrite /* pwrite dpdd 174 */
+ .word REGS(solaris_llseek) /* llseek dLd 175 */
+ .word solaris_unimplemented /* lwpself 176 */
+ .word solaris_unimplemented /* lwpinfo 177 */
+ .word solaris_unimplemented /* lwpprivate 178 */
+ .word solaris_unimplemented /* processorbind 179 */
+ .word solaris_unimplemented /* processorexbind 180 */
+ .word solaris_unimplemented /* 181 */
+ .word solaris_unimplemented /* sync_mailbox 182 */
+ .word solaris_unimplemented /* prepblock 183 */
+ .word solaris_unimplemented /* block 184 */
+ .word solaris_acl /* acl sddp 185 */
+ .word solaris_unimplemented /* unblock 186 */
+ .word solaris_unimplemented /* cancelblock 187 */
+ .word solaris_unimplemented /* ? 188 */
+ .word solaris_unimplemented /* xxxxx 189 */
+ .word solaris_unimplemented /* xxxxxe 190 */
+ .word solaris_unimplemented /* 191 */
+ .word solaris_unimplemented /* 192 */
+ .word solaris_unimplemented /* 193 */
+ .word solaris_unimplemented /* 194 */
+ .word solaris_unimplemented /* 195 */
+ .word solaris_unimplemented /* 196 */
+ .word solaris_unimplemented /* 197 */
+ .word solaris_unimplemented /* 198 */
+ .word CHAIN(nanosleep) /* nanosleep dd 199 */
+ .word solaris_facl /* facl dddp 200 */
+ .word solaris_unimplemented /* 201 */
+ .word solaris_unimplemented /* 202 */
+ .word solaris_unimplemented /* 203 */
+ .word solaris_unimplemented /* 204 */
+ .word solaris_unimplemented /* 205 */
+ .word solaris_unimplemented /* 206 */
+ .word solaris_unimplemented /* 207 */
+ .word solaris_unimplemented /* 208 */
+ .word solaris_unimplemented /* 209 */
+ .word solaris_unimplemented /* 210 */
+ .word solaris_unimplemented /* 211 */
+ .word solaris_unimplemented /* 212 */
+ .word solaris_unimplemented /* 213 */
+ .word solaris_unimplemented /* 214 */
+ .word solaris_unimplemented /* 215 */
+ .word solaris_unimplemented /* 216 */
+ .word solaris_unimplemented /* 217 */
+ .word solaris_unimplemented /* 218 */
+ .word solaris_unimplemented /* 219 */
+ .word solaris_unimplemented /* 220 */
+ .word solaris_unimplemented /* 221 */
+ .word solaris_unimplemented /* 222 */
+ .word solaris_unimplemented /* 223 */
+ .word solaris_unimplemented /* 224 */
+ .word solaris_unimplemented /* 225 */
+ .word solaris_unimplemented /* 226 */
+ .word solaris_unimplemented /* 227 */
+ .word solaris_unimplemented /* 228 */
+ .word solaris_unimplemented /* 229 */
+ .word solaris_unimplemented /* 230 */
+ .word solaris_unimplemented /* 231 */
+ .word solaris_unimplemented /* 232 */
+ .word solaris_unimplemented /* 233 */
+ .word solaris_unimplemented /* 234 */
+ .word solaris_unimplemented /* 235 */
+ .word solaris_unimplemented /* 236 */
+ .word solaris_unimplemented /* 237 */
+ .word solaris_unimplemented /* 238 */
+ .word solaris_unimplemented /* 239 */
+ .word solaris_unimplemented /* 240 */
+ .word solaris_unimplemented /* 241 */
+ .word solaris_unimplemented /* 242 */
+ .word solaris_unimplemented /* 243 */
+ .word solaris_unimplemented /* 244 */
+ .word solaris_unimplemented /* 245 */
+ .word solaris_unimplemented /* 246 */
+ .word solaris_unimplemented /* 247 */
+ .word solaris_unimplemented /* 248 */
+ .word solaris_unimplemented /* 249 */
+ .word solaris_unimplemented /* 250 */
+ .word solaris_unimplemented /* 251 */
+ .word solaris_unimplemented /* 252 */
+ .word solaris_unimplemented /* 253 */
+ .word solaris_unimplemented /* 254 */
+ .word solaris_unimplemented /* 255 */
+