fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / arch / sparc64 / solaris / misc.c
index cea38c0..bca16e8 100644 (file)
@@ -4,7 +4,6 @@
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  */
 
-#include <linux/config.h>
 #include <linux/module.h> 
 #include <linux/types.h>
 #include <linux/smp_lock.h>
@@ -12,6 +11,7 @@
 #include <linux/limits.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
+#include <linux/tty.h>
 #include <linux/mman.h>
 #include <linux/file.h>
 #include <linux/timex.h>
@@ -23,6 +23,7 @@
 #include <asm/oplib.h>
 #include <asm/idprom.h>
 #include <asm/smp.h>
+#include <asm/prom.h>
 
 #include "conv.h"
 
@@ -76,7 +77,7 @@ static u32 do_solaris_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u64 o
                if (!file)
                        goto out;
                else {
-                       struct inode * inode = file->f_dentry->d_inode;
+                       struct inode * inode = file->f_path.dentry->d_inode;
                        if(imajor(inode) == MEM_MAJOR &&
                           iminor(inode) == 5) {
                                flags |= MAP_ANONYMOUS;
@@ -90,7 +91,7 @@ static u32 do_solaris_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u64 o
        len = PAGE_ALIGN(len);
        if(!(flags & MAP_FIXED))
                addr = 0;
-       else if (len > 0xf0000000UL || addr > 0xf0000000UL - len)
+       else if (len > STACK_TOP32 || addr > STACK_TOP32 - len)
                goto out_putf;
        ret_type = flags & _MAP_NEW;
        flags &= ~_MAP_NEW;
@@ -102,7 +103,7 @@ static u32 do_solaris_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u64 o
                         (unsigned long) prot, (unsigned long) flags, off);
        up_write(&current->mm->mmap_sem);
        if(!ret_type)
-               retval = ((retval < 0xf0000000) ? 0 : retval);
+               retval = ((retval < STACK_TOP32) ? 0 : retval);
                                
 out_putf:
        if (file)
@@ -121,10 +122,10 @@ asmlinkage u32 solaris_mmap64(struct pt_regs *regs, u32 len, u32 prot, u32 flags
        u32 offlo;
        
        if (regs->u_regs[UREG_G1]) {
-               if (get_user (offlo, (u32 *)(long)((u32)regs->u_regs[UREG_I6] + 0x5c)))
+               if (get_user (offlo, (u32 __user *)(long)((u32)regs->u_regs[UREG_I6] + 0x5c)))
                        return -EFAULT;
        } else {
-               if (get_user (offlo, (u32 *)(long)((u32)regs->u_regs[UREG_I6] + 0x60)))
+               if (get_user (offlo, (u32 __user *)(long)((u32)regs->u_regs[UREG_I6] + 0x60)))
                        return -EFAULT;
        }
        return do_solaris_mmap((u32)regs->u_regs[UREG_I0], len, prot, flags, fd, (((u64)offhi)<<32)|offlo);
@@ -137,21 +138,34 @@ asmlinkage int solaris_brk(u32 brk)
        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);       \
-       if (copy_to_user(to, from, len))                                \
-               return -EFAULT;                                         \
-       if (dotchop)                                                    \
-               for (p=from,i=0; *p && *p != '.' && --len; p++,i++);    \
-       else                                                            \
-               i = len - 1;                                            \
-       if (__put_user('\0', (char *)(to+i)))                           \
-               return -EFAULT;                                         \
+static int __set_utsfield(char __user *to, int to_size,
+                         const char *from, int from_size,
+                         int dotchop, int countfrom)
+{
+       int len = countfrom ? (to_size > from_size ?
+                              from_size : to_size) : to_size;
+       int off;
+
+       if (copy_to_user(to, from, len))
+               return -EFAULT;
+
+       off = len < to_size? len: len - 1;
+       if (dotchop) {
+               const char *p = strnchr(from, len, '.');
+               if (p) off = p - from;
+       }
+
+       if (__put_user('\0', to + off))
+               return -EFAULT;
+
+       return 0;
 }
 
+#define set_utsfield(to, from, dotchop, countfrom) \
+       __set_utsfield((to), sizeof(to), \
+                      (from), sizeof(from), \
+                      (dotchop), (countfrom))
+
 struct sol_uname {
        char sysname[9];
        char nodename[9];
@@ -181,14 +195,17 @@ static char *machine(void)
        }
 }
 
-static char *platform(char *buffer)
+static char *platform(char *buffer, int sz)
 {
+       struct device_node *dp = of_find_node_by_path("/");
        int len;
 
        *buffer = 0;
-       len = prom_getproperty(prom_root_node, "name", buffer, 256);
-       if(len > 0)
-               buffer[len] = 0;
+       len = strlen(dp->name);
+       if (len > sz)
+               len = sz;
+       memcpy(buffer, dp->name, len);
+       buffer[len] = 0;
        if (*buffer) {
                char *p;
 
@@ -200,16 +217,22 @@ static char *platform(char *buffer)
        return "sun4u";
 }
 
-static char *serial(char *buffer)
+static char *serial(char *buffer, int sz)
 {
-       int node = prom_getchild(prom_root_node);
+       struct device_node *dp = of_find_node_by_path("/options");
        int len;
 
-       node = prom_searchsiblings(node, "options");
        *buffer = 0;
-       len = prom_getproperty(node, "system-board-serial#", buffer, 256);
-       if(len > 0)
-               buffer[len] = 0;
+       if (dp) {
+               char *val = of_get_property(dp, "system-board-serial#", &len);
+
+               if (val && len > 0) {
+                       if (len > sz)
+                               len = sz;
+                       memcpy(buffer, val, len);
+                       buffer[len] = 0;
+               }
+       }
        if (!*buffer)
                return "4512348717234";
        else
@@ -218,22 +241,21 @@ static char *serial(char *buffer)
 
 asmlinkage int solaris_utssys(u32 buf, u32 flags, int which, u32 buf2)
 {
+       struct sol_uname __user *v = A(buf);
+       int err;
+
        switch (which) {
        case 0: /* old uname */
                /* Let's cheat */
-               set_utsfield(((struct sol_uname *)A(buf))->sysname, 
-                       "SunOS", 1, 0);
+               err  = set_utsfield(v->sysname, "SunOS", 1, 0);
                down_read(&uts_sem);
-               set_utsfield(((struct sol_uname *)A(buf))->nodename, 
-                       system_utsname.nodename, 1, 1);
+               err |= set_utsfield(v->nodename, utsname()->nodename,
+                                   1, 1);
                up_read(&uts_sem);
-               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;
+               err |= set_utsfield(v->release, "2.6", 0, 0);
+               err |= set_utsfield(v->version, "Generic", 0, 0);
+               err |= set_utsfield(v->machine, machine(), 0, 0);
+               return (err ? -EFAULT : 0);
        case 2: /* ustat */
                return -ENOSYS;
        case 3: /* fusers */
@@ -245,20 +267,19 @@ asmlinkage int solaris_utssys(u32 buf, u32 flags, int which, u32 buf2)
 
 asmlinkage int solaris_utsname(u32 buf)
 {
+       struct sol_utsname __user *v = A(buf);
+       int err;
+
        /* Why should we not lie a bit? */
        down_read(&uts_sem);
-       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);
+       err  = set_utsfield(v->sysname, "SunOS", 0, 0);
+       err |= set_utsfield(v->nodename, utsname()->nodename, 1, 1);
+       err |= set_utsfield(v->release, "5.6", 0, 0);
+       err |= set_utsfield(v->version, "Generic", 0, 0);
+       err |= set_utsfield(v->machine, machine(), 0, 0);
        up_read(&uts_sem);
-       return 0;
+
+       return (err ? -EFAULT : 0);
 }
 
 #define SI_SYSNAME             1       /* return name of operating system */
@@ -284,7 +305,7 @@ asmlinkage int solaris_sysinfo(int cmd, u32 buf, s32 count)
        case SI_HOSTNAME:
                r = buffer + 256;
                down_read(&uts_sem);
-               for (p = system_utsname.nodename, q = buffer; 
+               for (p = utsname()->nodename, q = buffer;
                     q < r && *p && *p != '.'; *q++ = *p++);
                up_read(&uts_sem);
                *q = 0;
@@ -294,19 +315,19 @@ asmlinkage int solaris_sysinfo(int cmd, u32 buf, s32 count)
        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_HW_SERIAL: r = serial(buffer, sizeof(buffer)); break;
+       case SI_PLATFORM: r = platform(buffer, sizeof(buffer)); break;
        case SI_SRPC_DOMAIN: r = ""; break;
        case SI_VERSION: r = "Generic"; break;
        default: return -EINVAL;
        }
        len = strlen(r) + 1;
        if (count < len) {
-               if (copy_to_user((char *)A(buf), r, count - 1) ||
-                   __put_user(0, (char *)A(buf) + count - 1))
+               if (copy_to_user(A(buf), r, count - 1) ||
+                   __put_user(0, (char __user *)A(buf) + count - 1))
                        return -EFAULT;
        } else {
-               if (copy_to_user((char *)A(buf), r, len))
+               if (copy_to_user(A(buf), r, len))
                        return -EFAULT;
        }
        return len;
@@ -342,7 +363,7 @@ 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_CHILD_MAX:  return -1; /* no limit */
        case SOLARIS_CONFIG_OPEN_FILES: return OPEN_MAX;
        case SOLARIS_CONFIG_POSIX_VER:  return 199309;
        case SOLARIS_CONFIG_PAGESIZE:   return PAGE_SIZE;
@@ -402,7 +423,7 @@ asmlinkage int solaris_procids(int cmd, s32 pid, s32 pgid)
                           Solaris setpgrp and setsid? */
                        ret = sys_setpgid(0, 0);
                        if (ret) return ret;
-                       current->signal->tty = NULL;
+                       proc_clear_tty(current);
                        return process_group(current);
                }
        case 2: /* getsid */
@@ -453,7 +474,7 @@ struct rlimit32 {
        u32     rlim_max;
 };
 
-asmlinkage int solaris_getrlimit(unsigned int resource, struct rlimit32 *rlim)
+asmlinkage int solaris_getrlimit(unsigned int resource, struct rlimit32 __user *rlim)
 {
        struct rlimit r;
        int ret;
@@ -486,15 +507,15 @@ asmlinkage int solaris_getrlimit(unsigned int resource, struct rlimit32 *rlim)
        return ret;
 }
 
-asmlinkage int solaris_setrlimit(unsigned int resource, struct rlimit32 *rlim)
+asmlinkage int solaris_setrlimit(unsigned int resource, struct rlimit32 __user *rlim)
 {
        struct rlimit r, rold;
        int ret;
        mm_segment_t old_fs = get_fs ();
-       int (*sys_getrlimit)(unsigned int, struct rlimit *) =
-               (int (*)(unsigned int, struct rlimit *))SYS(getrlimit);
-       int (*sys_setrlimit)(unsigned int, struct rlimit *) =
-               (int (*)(unsigned int, struct rlimit *))SYS(setrlimit);
+       int (*sys_getrlimit)(unsigned int, struct rlimit __user *) =
+               (int (*)(unsigned int, struct rlimit __user *))SYS(getrlimit);
+       int (*sys_setrlimit)(unsigned int, struct rlimit __user *) =
+               (int (*)(unsigned int, struct rlimit __user *))SYS(setrlimit);
 
        if (resource > RLIMIT_SOL_VMEM)
                return -EINVAL; 
@@ -527,13 +548,13 @@ asmlinkage int solaris_setrlimit(unsigned int resource, struct rlimit32 *rlim)
        return ret;
 }
 
-asmlinkage int solaris_getrlimit64(unsigned int resource, struct rlimit *rlim)
+asmlinkage int solaris_getrlimit64(unsigned int resource, struct rlimit __user *rlim)
 {
        struct rlimit r;
        int ret;
        mm_segment_t old_fs = get_fs ();
-       int (*sys_getrlimit)(unsigned int, struct rlimit *) =
-               (int (*)(unsigned int, struct rlimit *))SYS(getrlimit);
+       int (*sys_getrlimit)(unsigned int, struct rlimit __user *) =
+               (int (*)(unsigned int, struct rlimit __user *))SYS(getrlimit);
 
        if (resource > RLIMIT_SOL_VMEM)
                return -EINVAL; 
@@ -556,15 +577,15 @@ asmlinkage int solaris_getrlimit64(unsigned int resource, struct rlimit *rlim)
        return ret;
 }
 
-asmlinkage int solaris_setrlimit64(unsigned int resource, struct rlimit *rlim)
+asmlinkage int solaris_setrlimit64(unsigned int resource, struct rlimit __user *rlim)
 {
        struct rlimit r, rold;
        int ret;
        mm_segment_t old_fs = get_fs ();
-       int (*sys_getrlimit)(unsigned int, struct rlimit *) =
-               (int (*)(unsigned int, struct rlimit *))SYS(getrlimit);
-       int (*sys_setrlimit)(unsigned int, struct rlimit *) =
-               (int (*)(unsigned int, struct rlimit *))SYS(setrlimit);
+       int (*sys_getrlimit)(unsigned int, struct rlimit __user *) =
+               (int (*)(unsigned int, struct rlimit __user *))SYS(getrlimit);
+       int (*sys_setrlimit)(unsigned int, struct rlimit __user *) =
+               (int (*)(unsigned int, struct rlimit __user *))SYS(setrlimit);
 
        if (resource > RLIMIT_SOL_VMEM)
                return -EINVAL; 
@@ -623,10 +644,10 @@ struct sol_timex {
        s32 stbcnt;
 };
 
-asmlinkage int solaris_ntp_gettime(struct sol_ntptimeval *ntp)
+asmlinkage int solaris_ntp_gettime(struct sol_ntptimeval __user *ntp)
 {
-       int (*sys_adjtimex)(struct timex *) =
-               (int (*)(struct timex *))SYS(adjtimex);
+       int (*sys_adjtimex)(struct timex __user *) =
+               (int (*)(struct timex __user *))SYS(adjtimex);
        struct timex t;
        int ret;
        mm_segment_t old_fs = get_fs();
@@ -644,10 +665,10 @@ asmlinkage int solaris_ntp_gettime(struct sol_ntptimeval *ntp)
        return ret;                             
 }
 
-asmlinkage int solaris_ntp_adjtime(struct sol_timex *txp)
+asmlinkage int solaris_ntp_adjtime(struct sol_timex __user *txp)
 {
-       int (*sys_adjtimex)(struct timex *) =
-               (int (*)(struct timex *))SYS(adjtimex);
+       int (*sys_adjtimex)(struct timex __user *) =
+               (int (*)(struct timex __user *))SYS(adjtimex);
        struct timex t;
        int ret, err;
        mm_segment_t old_fs = get_fs();
@@ -716,19 +737,15 @@ struct exec_domain solaris_exec_domain = {
 
 extern int init_socksys(void);
 
-#ifdef MODULE
-
 MODULE_AUTHOR("Jakub Jelinek (jj@ultra.linux.cz), Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz)");
 MODULE_DESCRIPTION("Solaris binary emulation module");
 MODULE_LICENSE("GPL");
 
-#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 
+       wmb();          \
+       __asm__ __volatile__ ("flush %0" : : "r" (&tl0_solaris[3]))
 
 extern u32 solaris_sparc_syscall[];
 extern u32 solaris_syscall[];
@@ -736,7 +753,7 @@ extern void cleanup_socksys(void);
 
 extern u32 entry64_personality_patch;
 
-int init_module(void)
+static int __init solaris_init(void)
 {
        int ret;
 
@@ -750,24 +767,18 @@ int init_module(void)
        entry64_personality_patch |=
                (offsetof(struct task_struct, personality) +
                 (sizeof(unsigned long) - 1));
-       __asm__ __volatile__("membar #StoreStore; flush %0"
+       wmb();
+       __asm__ __volatile__("flush %0"
                             : : "r" (&entry64_personality_patch));
        return 0;
 }
 
-void cleanup_module(void)
+static void __exit solaris_exit(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();
-       return 0;
-}
-#endif
-
+module_init(solaris_init);
+module_exit(solaris_exit);