File: /usr/src/linux/arch/sparc64/solaris/misc.c

1     /* $Id: misc.c,v 1.33 2001/09/18 22:29:06 davem Exp $
2      * misc.c: Miscelaneous syscall emulation for Solaris
3      *
4      * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
5      */
6     
7     #include <linux/config.h>
8     #include <linux/module.h> 
9     #include <linux/types.h>
10     #include <linux/smp_lock.h>
11     #include <linux/utsname.h>
12     #include <linux/limits.h>
13     #include <linux/mm.h>
14     #include <linux/smp.h>
15     #include <linux/mman.h>
16     #include <linux/file.h>
17     #include <linux/timex.h>
18     
19     #include <asm/uaccess.h>
20     #include <asm/string.h>
21     #include <asm/oplib.h>
22     #include <asm/idprom.h>
23     
24     #include "conv.h"
25     
26     /* Conversion from Linux to Solaris errnos. 0-34 are identity mapped.
27        Some Linux errnos (EPROCLIM, EDOTDOT, ERREMOTE, EUCLEAN, ENOTNAM, 
28        ENAVAIL, EISNAM, EREMOTEIO, ENOMEDIUM, EMEDIUMTYPE) have no Solaris
29        equivalents. I return EINVAL in that case, which is very wrong. If
30        someone suggest a better value for them, you're welcomed.
31        On the other side, Solaris ECANCELED and ENOTSUP have no Linux equivalents,
32        but that doesn't matter here. --jj */
33     int solaris_err_table[] = {
34     /* 0 */  0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
35     /* 10 */  10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
36     /* 20 */  20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
37     /* 30 */  30, 31, 32, 33, 34, 22, 150, 149, 95, 96,
38     /* 40 */  97, 98, 99, 120, 121, 122, 123, 124, 125, 126, 
39     /* 50 */ 127, 128, 129, 130, 131, 132, 133, 134, 143, 144,
40     /* 60 */ 145, 146, 90, 78, 147, 148, 93, 22, 94, 49,
41     /* 70 */ 151, 66, 60, 62, 63, 35, 77, 36, 45, 46, 
42     /* 80 */ 64, 22, 67, 68, 69, 70, 71, 74, 22, 82, 
43     /* 90 */ 89, 92, 79, 81, 37, 38, 39, 40, 41, 42,
44     /* 100 */ 43, 44, 50, 51, 52, 53, 54, 55, 56, 57,
45     /* 110 */ 87, 61, 84, 65, 83, 80, 91, 22, 22, 22,
46     /* 120 */ 22, 22, 88, 86, 85, 22, 22,
47     };
48     
49     #define SOLARIS_NR_OPEN	256
50     
51     static u32 do_solaris_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u64 off)
52     {
53     	struct file *file = NULL;
54     	unsigned long retval, ret_type;
55     
56     	/* Do we need it here? */
57     	set_personality(PER_SVR4);
58     	if (flags & MAP_NORESERVE) {
59     		static int cnt = 0;
60     		
61     		if (cnt < 5) {
62     			printk("%s:  unimplemented Solaris MAP_NORESERVE mmap() flag\n",
63     			       current->comm);
64     			cnt++;
65     		}
66     		flags &= ~MAP_NORESERVE;
67     	}
68     	retval = -EBADF;
69     	if(!(flags & MAP_ANONYMOUS)) {
70     		if(fd >= SOLARIS_NR_OPEN)
71     			goto out;
72      		file = fget(fd);
73     		if (!file)
74     			goto out;
75     		else {
76     			struct inode * inode = file->f_dentry->d_inode;
77     			if(MAJOR(inode->i_rdev) == MEM_MAJOR &&
78     			   MINOR(inode->i_rdev) == 5) {
79     				flags |= MAP_ANONYMOUS;
80     				fput(file);
81     				file = NULL;
82     			}
83     		}
84     	}
85     
86     	retval = -EINVAL;
87     	len = PAGE_ALIGN(len);
88     	if(!(flags & MAP_FIXED))
89     		addr = 0;
90     	else if (len > 0xf0000000UL || addr > 0xf0000000UL - len)
91     		goto out_putf;
92     	ret_type = flags & _MAP_NEW;
93     	flags &= ~_MAP_NEW;
94     
95     	down_write(&current->mm->mmap_sem);
96     	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
97     	retval = do_mmap(file,
98     			 (unsigned long) addr, (unsigned long) len,
99     			 (unsigned long) prot, (unsigned long) flags, off);
100     	up_write(&current->mm->mmap_sem);
101     	if(!ret_type)
102     		retval = ((retval < 0xf0000000) ? 0 : retval);
103     	                        
104     out_putf:
105     	if (file)
106     		fput(file);
107     out:
108     	return (u32) retval;
109     }
110     
111     asmlinkage u32 solaris_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 off)
112     {
113     	return do_solaris_mmap(addr, len, prot, flags, fd, (u64) off);
114     }
115     
116     asmlinkage u32 solaris_mmap64(struct pt_regs *regs, u32 len, u32 prot, u32 flags, u32 fd, u32 offhi)
117     {
118     	u32 offlo;
119     	
120     	if (regs->u_regs[UREG_G1]) {
121     		if (get_user (offlo, (u32 *)(long)((u32)regs->u_regs[UREG_I6] + 0x5c)))
122     			return -EFAULT;
123     	} else {
124     		if (get_user (offlo, (u32 *)(long)((u32)regs->u_regs[UREG_I6] + 0x60)))
125     			return -EFAULT;
126     	}
127     	return do_solaris_mmap((u32)regs->u_regs[UREG_I0], len, prot, flags, fd, (((u64)offhi)<<32)|offlo);
128     }
129     
130     asmlinkage int solaris_brk(u32 brk)
131     {
132     	int (*sunos_brk)(u32) = (int (*)(u32))SUNOS(17);
133     	
134     	return sunos_brk(brk);
135     }
136     
137     #define set_utsfield(to, from, dotchop, countfrom) {			\
138     	char *p; 							\
139     	int i, len = (countfrom) ? 					\
140     		((sizeof(to) > sizeof(from) ? 				\
141     			sizeof(from) : sizeof(to))) : sizeof(to); 	\
142     	if (copy_to_user(to, from, len))				\
143     		return -EFAULT;						\
144     	if (dotchop) 							\
145     		for (p=from,i=0; *p && *p != '.' && --len; p++,i++); 	\
146     	else 								\
147     		i = len - 1; 						\
148     	if (__put_user('\0', (char *)(to+i)))				\
149     		return -EFAULT;						\
150     }
151     
152     struct sol_uname {
153     	char sysname[9];
154     	char nodename[9];
155     	char release[9];
156     	char version[9];
157     	char machine[9];
158     };
159     
160     struct sol_utsname {
161     	char sysname[257];
162     	char nodename[257];
163     	char release[257];
164     	char version[257];
165     	char machine[257];
166     };
167     
168     static char *machine(void)
169     {
170     	switch (sparc_cpu_model) {
171     	case sun4: return "sun4";
172     	case sun4c: return "sun4c";
173     	case sun4e: return "sun4e";
174     	case sun4m: return "sun4m";
175     	case sun4d: return "sun4d";
176     	case sun4u: return "sun4u";
177     	default: return "sparc";
178     	}
179     }
180     
181     static char *platform(char *buffer)
182     {
183     	int len;
184     
185     	*buffer = 0;
186     	len = prom_getproperty(prom_root_node, "name", buffer, 256);
187     	if(len > 0)
188     		buffer[len] = 0;
189     	if (*buffer) {
190     		char *p;
191     
192     		for (p = buffer; *p; p++)
193     			if (*p == '/' || *p == ' ') *p = '_';
194     		return buffer;
195     	}
196     
197     	return "sun4u";
198     }
199     
200     static char *serial(char *buffer)
201     {
202     	int node = prom_getchild(prom_root_node);
203     	int len;
204     
205     	node = prom_searchsiblings(node, "options");
206     	*buffer = 0;
207     	len = prom_getproperty(node, "system-board-serial#", buffer, 256);
208     	if(len > 0)
209     		buffer[len] = 0;
210     	if (!*buffer)
211     		return "4512348717234";
212     	else
213     		return buffer;
214     }
215     
216     asmlinkage int solaris_utssys(u32 buf, u32 flags, int which, u32 buf2)
217     {
218     	switch (which) {
219     	case 0:	/* old uname */
220     		/* Let's cheat */
221     		set_utsfield(((struct sol_uname *)A(buf))->sysname, 
222     			"SunOS", 1, 0);
223     		down_read(&uts_sem);
224     		set_utsfield(((struct sol_uname *)A(buf))->nodename, 
225     			system_utsname.nodename, 1, 1);
226     		up_read(&uts_sem);
227     		set_utsfield(((struct sol_uname *)A(buf))->release, 
228     			"2.6", 0, 0);
229     		set_utsfield(((struct sol_uname *)A(buf))->version, 
230     			"Generic", 0, 0);
231     		set_utsfield(((struct sol_uname *)A(buf))->machine, 
232     			machine(), 0, 0);
233     		return 0;
234     	case 2: /* ustat */
235     		return -ENOSYS;
236     	case 3: /* fusers */
237     		return -ENOSYS;
238     	default:
239     		return -ENOSYS;
240     	}
241     }
242     
243     asmlinkage int solaris_utsname(u32 buf)
244     {
245     	/* Why should we not lie a bit? */
246     	down_read(&uts_sem);
247     	set_utsfield(((struct sol_utsname *)A(buf))->sysname, 
248     			"SunOS", 0, 0);
249     	set_utsfield(((struct sol_utsname *)A(buf))->nodename, 
250     			system_utsname.nodename, 1, 1);
251     	set_utsfield(((struct sol_utsname *)A(buf))->release, 
252     			"5.6", 0, 0);
253     	set_utsfield(((struct sol_utsname *)A(buf))->version, 
254     			"Generic", 0, 0);
255     	set_utsfield(((struct sol_utsname *)A(buf))->machine, 
256     			machine(), 0, 0);
257     	up_read(&uts_sem);
258     	return 0;
259     }
260     
261     #define SI_SYSNAME		1       /* return name of operating system */
262     #define SI_HOSTNAME		2       /* return name of node */
263     #define SI_RELEASE		3       /* return release of operating system */
264     #define SI_VERSION		4       /* return version field of utsname */
265     #define SI_MACHINE		5       /* return kind of machine */
266     #define SI_ARCHITECTURE		6       /* return instruction set arch */
267     #define SI_HW_SERIAL		7       /* return hardware serial number */
268     #define SI_HW_PROVIDER		8       /* return hardware manufacturer */
269     #define SI_SRPC_DOMAIN		9       /* return secure RPC domain */
270     #define SI_PLATFORM		513     /* return platform identifier */
271     
272     asmlinkage int solaris_sysinfo(int cmd, u32 buf, s32 count)
273     {
274     	char *p, *q, *r;
275     	char buffer[256];
276     	int len;
277     	
278     	/* Again, we cheat :)) */
279     	switch (cmd) {
280     	case SI_SYSNAME: r = "SunOS"; break;
281     	case SI_HOSTNAME:
282     		r = buffer + 256;
283     		down_read(&uts_sem);
284     		for (p = system_utsname.nodename, q = buffer; 
285     		     q < r && *p && *p != '.'; *q++ = *p++);
286     		up_read(&uts_sem);
287     		*q = 0;
288     		r = buffer;
289     		break;
290     	case SI_RELEASE: r = "5.6"; break;
291     	case SI_MACHINE: r = machine(); break;
292     	case SI_ARCHITECTURE: r = "sparc"; break;
293     	case SI_HW_PROVIDER: r = "Sun_Microsystems"; break;
294     	case SI_HW_SERIAL: r = serial(buffer); break;
295     	case SI_PLATFORM: r = platform(buffer); break;
296     	case SI_SRPC_DOMAIN: r = ""; break;
297     	case SI_VERSION: r = "Generic"; break;
298     	default: return -EINVAL;
299     	}
300     	len = strlen(r) + 1;
301     	if (count < len) {
302     		if (copy_to_user((char *)A(buf), r, count - 1) ||
303     		    __put_user(0, (char *)A(buf) + count - 1))
304     			return -EFAULT;
305     	} else {
306     		if (copy_to_user((char *)A(buf), r, len))
307     			return -EFAULT;
308     	}
309     	return len;
310     }
311     
312     #define	SOLARIS_CONFIG_NGROUPS			2
313     #define	SOLARIS_CONFIG_CHILD_MAX		3
314     #define	SOLARIS_CONFIG_OPEN_FILES		4
315     #define	SOLARIS_CONFIG_POSIX_VER		5
316     #define	SOLARIS_CONFIG_PAGESIZE			6
317     #define	SOLARIS_CONFIG_CLK_TCK			7
318     #define	SOLARIS_CONFIG_XOPEN_VER		8
319     #define	SOLARIS_CONFIG_PROF_TCK			10
320     #define	SOLARIS_CONFIG_NPROC_CONF		11
321     #define	SOLARIS_CONFIG_NPROC_ONLN		12
322     #define	SOLARIS_CONFIG_AIO_LISTIO_MAX		13
323     #define	SOLARIS_CONFIG_AIO_MAX			14
324     #define	SOLARIS_CONFIG_AIO_PRIO_DELTA_MAX	15
325     #define	SOLARIS_CONFIG_DELAYTIMER_MAX		16
326     #define	SOLARIS_CONFIG_MQ_OPEN_MAX		17
327     #define	SOLARIS_CONFIG_MQ_PRIO_MAX		18
328     #define	SOLARIS_CONFIG_RTSIG_MAX		19
329     #define	SOLARIS_CONFIG_SEM_NSEMS_MAX		20
330     #define	SOLARIS_CONFIG_SEM_VALUE_MAX		21
331     #define	SOLARIS_CONFIG_SIGQUEUE_MAX		22
332     #define	SOLARIS_CONFIG_SIGRT_MIN		23
333     #define	SOLARIS_CONFIG_SIGRT_MAX		24
334     #define	SOLARIS_CONFIG_TIMER_MAX		25
335     #define	SOLARIS_CONFIG_PHYS_PAGES		26
336     #define	SOLARIS_CONFIG_AVPHYS_PAGES		27
337     
338     extern unsigned prom_cpu_nodes[NR_CPUS];
339     
340     asmlinkage int solaris_sysconf(int id)
341     {
342     	switch (id) {
343     	case SOLARIS_CONFIG_NGROUPS:	return NGROUPS_MAX;
344     	case SOLARIS_CONFIG_CHILD_MAX:	return CHILD_MAX;
345     	case SOLARIS_CONFIG_OPEN_FILES:	return OPEN_MAX;
346     	case SOLARIS_CONFIG_POSIX_VER:	return 199309;
347     	case SOLARIS_CONFIG_PAGESIZE:	return PAGE_SIZE;
348     	case SOLARIS_CONFIG_XOPEN_VER:	return 3;
349     	case SOLARIS_CONFIG_CLK_TCK:
350     	case SOLARIS_CONFIG_PROF_TCK:
351     		return prom_getintdefault(prom_cpu_nodes[smp_processor_id()],
352     					  "clock-frequency", 167000000);
353     #ifdef CONFIG_SMP	
354     	case SOLARIS_CONFIG_NPROC_CONF:	return NR_CPUS;
355     	case SOLARIS_CONFIG_NPROC_ONLN:	return smp_num_cpus;
356     #else
357     	case SOLARIS_CONFIG_NPROC_CONF:	return 1;
358     	case SOLARIS_CONFIG_NPROC_ONLN:	return 1;
359     #endif
360     	case SOLARIS_CONFIG_SIGRT_MIN:		return 37;
361     	case SOLARIS_CONFIG_SIGRT_MAX:		return 44;
362     	case SOLARIS_CONFIG_PHYS_PAGES:
363     	case SOLARIS_CONFIG_AVPHYS_PAGES:
364     		{
365     			struct sysinfo s;
366     			
367     			si_meminfo(&s);
368     			if (id == SOLARIS_CONFIG_PHYS_PAGES)
369     				return s.totalram >>= PAGE_SHIFT;
370     			else
371     				return s.freeram >>= PAGE_SHIFT;
372     		}
373     	/* XXX support these as well -jj */
374     	case SOLARIS_CONFIG_AIO_LISTIO_MAX:	return -EINVAL;
375     	case SOLARIS_CONFIG_AIO_MAX:		return -EINVAL;
376     	case SOLARIS_CONFIG_AIO_PRIO_DELTA_MAX:	return -EINVAL;
377     	case SOLARIS_CONFIG_DELAYTIMER_MAX:	return -EINVAL;
378     	case SOLARIS_CONFIG_MQ_OPEN_MAX:	return -EINVAL;
379     	case SOLARIS_CONFIG_MQ_PRIO_MAX:	return -EINVAL;
380     	case SOLARIS_CONFIG_RTSIG_MAX:		return -EINVAL;
381     	case SOLARIS_CONFIG_SEM_NSEMS_MAX:	return -EINVAL;
382     	case SOLARIS_CONFIG_SEM_VALUE_MAX:	return -EINVAL;
383     	case SOLARIS_CONFIG_SIGQUEUE_MAX:	return -EINVAL;
384     	case SOLARIS_CONFIG_TIMER_MAX:		return -EINVAL;
385     	default: return -EINVAL;
386     	}
387     }
388     
389     asmlinkage int solaris_procids(int cmd, s32 pid, s32 pgid)
390     {
391     	int ret;
392     	
393     	switch (cmd) {
394     	case 0: /* getpgrp */
395     		return current->pgrp;
396     	case 1: /* setpgrp */
397     		{
398     			int (*sys_setpgid)(pid_t,pid_t) =
399     				(int (*)(pid_t,pid_t))SYS(setpgid);
400     				
401     			/* can anyone explain me the difference between
402     			   Solaris setpgrp and setsid? */
403     			ret = sys_setpgid(0, 0);
404     			if (ret) return ret;
405     			current->tty = NULL;
406     			return current->pgrp;
407     		}
408     	case 2: /* getsid */
409     		{
410     			int (*sys_getsid)(pid_t) = (int (*)(pid_t))SYS(getsid);
411     			return sys_getsid(pid);
412     		}
413     	case 3: /* setsid */
414     		{
415     			int (*sys_setsid)(void) = (int (*)(void))SYS(setsid);
416     			return sys_setsid();
417     		}
418     	case 4: /* getpgid */
419     		{
420     			int (*sys_getpgid)(pid_t) = (int (*)(pid_t))SYS(getpgid);
421     			return sys_getpgid(pid);
422     		}
423     	case 5: /* setpgid */
424     		{
425     			int (*sys_setpgid)(pid_t,pid_t) = 
426     				(int (*)(pid_t,pid_t))SYS(setpgid);
427     			return sys_setpgid(pid,pgid);
428     		}
429     	}
430     	return -EINVAL;
431     }
432     
433     asmlinkage int solaris_gettimeofday(u32 tim)
434     {
435     	int (*sys_gettimeofday)(struct timeval *, struct timezone *) =
436     		(int (*)(struct timeval *, struct timezone *))SYS(gettimeofday);
437     		
438     	return sys_gettimeofday((struct timeval *)(u64)tim, NULL);
439     }
440     
441     #define RLIM_SOL_INFINITY32	0x7fffffff
442     #define RLIM_SOL_SAVED_MAX32	0x7ffffffe
443     #define RLIM_SOL_SAVED_CUR32	0x7ffffffd
444     #define RLIM_SOL_INFINITY	((u64)-3)
445     #define RLIM_SOL_SAVED_MAX	((u64)-2)
446     #define RLIM_SOL_SAVED_CUR	((u64)-1)
447     #define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
448     #define RLIMIT_SOL_NOFILE	5
449     #define RLIMIT_SOL_VMEM		6
450     
451     struct rlimit32 {
452     	u32	rlim_cur;
453     	u32	rlim_max;
454     };
455     
456     asmlinkage int solaris_getrlimit(unsigned int resource, struct rlimit32 *rlim)
457     {
458     	struct rlimit r;
459     	int ret;
460     	mm_segment_t old_fs = get_fs ();
461     	int (*sys_getrlimit)(unsigned int, struct rlimit *) =
462     		(int (*)(unsigned int, struct rlimit *))SYS(getrlimit);
463     
464     	if (resource > RLIMIT_SOL_VMEM)
465     		return -EINVAL;	
466     	switch (resource) {
467     	case RLIMIT_SOL_NOFILE: resource = RLIMIT_NOFILE; break;
468     	case RLIMIT_SOL_VMEM: resource = RLIMIT_AS; break;
469     	default: break;
470     	}
471     	set_fs (KERNEL_DS);
472     	ret = sys_getrlimit(resource, &r);
473     	set_fs (old_fs);
474     	if (!ret) {
475     		if (r.rlim_cur == RLIM_INFINITY)
476     			r.rlim_cur = RLIM_SOL_INFINITY32;
477     		else if ((u64)r.rlim_cur > RLIM_SOL_INFINITY32)
478     			r.rlim_cur = RLIM_SOL_SAVED_CUR32;
479     		if (r.rlim_max == RLIM_INFINITY)
480     			r.rlim_max = RLIM_SOL_INFINITY32;
481     		else if ((u64)r.rlim_max > RLIM_SOL_INFINITY32)
482     			r.rlim_max = RLIM_SOL_SAVED_MAX32;
483     		ret = put_user (r.rlim_cur, &rlim->rlim_cur);
484     		ret |= __put_user (r.rlim_max, &rlim->rlim_max);
485     	}
486     	return ret;
487     }
488     
489     asmlinkage int solaris_setrlimit(unsigned int resource, struct rlimit32 *rlim)
490     {
491     	struct rlimit r, rold;
492     	int ret;
493     	mm_segment_t old_fs = get_fs ();
494     	int (*sys_getrlimit)(unsigned int, struct rlimit *) =
495     		(int (*)(unsigned int, struct rlimit *))SYS(getrlimit);
496     	int (*sys_setrlimit)(unsigned int, struct rlimit *) =
497     		(int (*)(unsigned int, struct rlimit *))SYS(setrlimit);
498     
499     	if (resource > RLIMIT_SOL_VMEM)
500     		return -EINVAL;	
501     	switch (resource) {
502     	case RLIMIT_SOL_NOFILE: resource = RLIMIT_NOFILE; break;
503     	case RLIMIT_SOL_VMEM: resource = RLIMIT_AS; break;
504     	default: break;
505     	}
506     	if (get_user (r.rlim_cur, &rlim->rlim_cur) ||
507     	    __get_user (r.rlim_max, &rlim->rlim_max))
508     		return -EFAULT;
509     	set_fs (KERNEL_DS);
510     	ret = sys_getrlimit(resource, &rold);
511     	if (!ret) {
512     		if (r.rlim_cur == RLIM_SOL_INFINITY32)
513     			r.rlim_cur = RLIM_INFINITY;
514     		else if (r.rlim_cur == RLIM_SOL_SAVED_CUR32)
515     			r.rlim_cur = rold.rlim_cur;
516     		else if (r.rlim_cur == RLIM_SOL_SAVED_MAX32)
517     			r.rlim_cur = rold.rlim_max;
518     		if (r.rlim_max == RLIM_SOL_INFINITY32)
519     			r.rlim_max = RLIM_INFINITY;
520     		else if (r.rlim_max == RLIM_SOL_SAVED_CUR32)
521     			r.rlim_max = rold.rlim_cur;
522     		else if (r.rlim_max == RLIM_SOL_SAVED_MAX32)
523     			r.rlim_max = rold.rlim_max;
524     		ret = sys_setrlimit(resource, &r);
525     	}
526     	set_fs (old_fs);
527     	return ret;
528     }
529     
530     asmlinkage int solaris_getrlimit64(unsigned int resource, struct rlimit *rlim)
531     {
532     	struct rlimit r;
533     	int ret;
534     	mm_segment_t old_fs = get_fs ();
535     	int (*sys_getrlimit)(unsigned int, struct rlimit *) =
536     		(int (*)(unsigned int, struct rlimit *))SYS(getrlimit);
537     
538     	if (resource > RLIMIT_SOL_VMEM)
539     		return -EINVAL;	
540     	switch (resource) {
541     	case RLIMIT_SOL_NOFILE: resource = RLIMIT_NOFILE; break;
542     	case RLIMIT_SOL_VMEM: resource = RLIMIT_AS; break;
543     	default: break;
544     	}
545     	set_fs (KERNEL_DS);
546     	ret = sys_getrlimit(resource, &r);
547     	set_fs (old_fs);
548     	if (!ret) {
549     		if (r.rlim_cur == RLIM_INFINITY)
550     			r.rlim_cur = RLIM_SOL_INFINITY;
551     		if (r.rlim_max == RLIM_INFINITY)
552     			r.rlim_max = RLIM_SOL_INFINITY;
553     		ret = put_user (r.rlim_cur, &rlim->rlim_cur);
554     		ret |= __put_user (r.rlim_max, &rlim->rlim_max);
555     	}
556     	return ret;
557     }
558     
559     asmlinkage int solaris_setrlimit64(unsigned int resource, struct rlimit *rlim)
560     {
561     	struct rlimit r, rold;
562     	int ret;
563     	mm_segment_t old_fs = get_fs ();
564     	int (*sys_getrlimit)(unsigned int, struct rlimit *) =
565     		(int (*)(unsigned int, struct rlimit *))SYS(getrlimit);
566     	int (*sys_setrlimit)(unsigned int, struct rlimit *) =
567     		(int (*)(unsigned int, struct rlimit *))SYS(setrlimit);
568     
569     	if (resource > RLIMIT_SOL_VMEM)
570     		return -EINVAL;	
571     	switch (resource) {
572     	case RLIMIT_SOL_NOFILE: resource = RLIMIT_NOFILE; break;
573     	case RLIMIT_SOL_VMEM: resource = RLIMIT_AS; break;
574     	default: break;
575     	}
576     	if (get_user (r.rlim_cur, &rlim->rlim_cur) ||
577     	    __get_user (r.rlim_max, &rlim->rlim_max))
578     		return -EFAULT;
579     	set_fs (KERNEL_DS);
580     	ret = sys_getrlimit(resource, &rold);
581     	if (!ret) {
582     		if (r.rlim_cur == RLIM_SOL_INFINITY)
583     			r.rlim_cur = RLIM_INFINITY;
584     		else if (r.rlim_cur == RLIM_SOL_SAVED_CUR)
585     			r.rlim_cur = rold.rlim_cur;
586     		else if (r.rlim_cur == RLIM_SOL_SAVED_MAX)
587     			r.rlim_cur = rold.rlim_max;
588     		if (r.rlim_max == RLIM_SOL_INFINITY)
589     			r.rlim_max = RLIM_INFINITY;
590     		else if (r.rlim_max == RLIM_SOL_SAVED_CUR)
591     			r.rlim_max = rold.rlim_cur;
592     		else if (r.rlim_max == RLIM_SOL_SAVED_MAX)
593     			r.rlim_max = rold.rlim_max;
594     		ret = sys_setrlimit(resource, &r);
595     	}
596     	set_fs (old_fs);
597     	return ret;
598     }
599     
600     struct timeval32 {
601     	int tv_sec, tv_usec;
602     };
603     
604     struct sol_ntptimeval {
605     	struct timeval32 time;
606     	s32 maxerror;
607     	s32 esterror;
608     };
609     
610     struct sol_timex {
611     	u32 modes;
612     	s32 offset;
613     	s32 freq;
614     	s32 maxerror;
615     	s32 esterror;
616     	s32 status;
617     	s32 constant;
618     	s32 precision;
619     	s32 tolerance;
620     	s32 ppsfreq;
621     	s32 jitter;
622     	s32 shift;
623     	s32 stabil;
624     	s32 jitcnt;
625     	s32 calcnt;
626     	s32 errcnt;
627     	s32 stbcnt;
628     };
629     
630     asmlinkage int solaris_ntp_gettime(struct sol_ntptimeval *ntp)
631     {
632     	int (*sys_adjtimex)(struct timex *) =
633     		(int (*)(struct timex *))SYS(adjtimex);
634     	struct timex t;
635     	int ret;
636     	mm_segment_t old_fs = get_fs();
637     	
638     	set_fs(KERNEL_DS);
639     	t.modes = 0;
640     	ret = sys_adjtimex(&t);
641     	set_fs(old_fs);
642     	if (ret < 0)
643     		return ret;
644     	ret = put_user (t.time.tv_sec, &ntp->time.tv_sec);
645     	ret |= __put_user (t.time.tv_usec, &ntp->time.tv_usec);
646     	ret |= __put_user (t.maxerror, &ntp->maxerror);
647     	ret |= __put_user (t.esterror, &ntp->esterror);
648     	return ret;	                        
649     }
650     
651     asmlinkage int solaris_ntp_adjtime(struct sol_timex *txp)
652     {
653     	int (*sys_adjtimex)(struct timex *) =
654     		(int (*)(struct timex *))SYS(adjtimex);
655     	struct timex t;
656     	int ret, err;
657     	mm_segment_t old_fs = get_fs();
658     
659     	ret = get_user (t.modes, &txp->modes);
660     	ret |= __get_user (t.offset, &txp->offset);
661     	ret |= __get_user (t.freq, &txp->freq);
662     	ret |= __get_user (t.maxerror, &txp->maxerror);
663     	ret |= __get_user (t.esterror, &txp->esterror);
664     	ret |= __get_user (t.status, &txp->status);
665     	ret |= __get_user (t.constant, &txp->constant);
666     	set_fs(KERNEL_DS);
667     	ret = sys_adjtimex(&t);
668     	set_fs(old_fs);
669     	if (ret < 0)
670     		return ret;
671     	err = put_user (t.offset, &txp->offset);
672     	err |= __put_user (t.freq, &txp->freq);
673     	err |= __put_user (t.maxerror, &txp->maxerror);
674     	err |= __put_user (t.esterror, &txp->esterror);
675     	err |= __put_user (t.status, &txp->status);
676     	err |= __put_user (t.constant, &txp->constant);
677     	err |= __put_user (t.precision, &txp->precision);
678     	err |= __put_user (t.tolerance, &txp->tolerance);
679     	err |= __put_user (t.ppsfreq, &txp->ppsfreq);
680     	err |= __put_user (t.jitter, &txp->jitter);
681     	err |= __put_user (t.shift, &txp->shift);
682     	err |= __put_user (t.stabil, &txp->stabil);
683     	err |= __put_user (t.jitcnt, &txp->jitcnt);
684     	err |= __put_user (t.calcnt, &txp->calcnt);
685     	err |= __put_user (t.errcnt, &txp->errcnt);
686     	err |= __put_user (t.stbcnt, &txp->stbcnt);
687     	if (err)
688     		return -EFAULT;
689     	return ret;
690     }
691     
692     asmlinkage int do_sol_unimplemented(struct pt_regs *regs)
693     {
694     	printk ("Unimplemented Solaris syscall %d %08x %08x %08x %08x\n", 
695     			(int)regs->u_regs[UREG_G1], 
696     			(int)regs->u_regs[UREG_I0],
697     			(int)regs->u_regs[UREG_I1],
698     			(int)regs->u_regs[UREG_I2],
699     			(int)regs->u_regs[UREG_I3]);
700     	return -ENOSYS;
701     }
702     
703     asmlinkage void solaris_register(void)
704     {
705     	set_personality(PER_SVR4);
706     }
707     
708     extern long solaris_to_linux_signals[], linux_to_solaris_signals[];
709     
710     struct exec_domain solaris_exec_domain = {
711     	name:		"Solaris",
712     	handler:	NULL,
713     	pers_low:	1,		/* PER_SVR4 personality */
714     	pers_high:	1,
715     	signal_map:	solaris_to_linux_signals,
716     	signal_invmap:	linux_to_solaris_signals,
717     	module:		THIS_MODULE,
718     	next:		NULL
719     };
720     
721     extern int init_socksys(void);
722     
723     #ifdef MODULE
724     
725     MODULE_AUTHOR("Jakub Jelinek (jj@ultra.linux.cz), Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz)");
726     MODULE_DESCRIPTION("Solaris binary emulation module");
727     EXPORT_NO_SYMBOLS;
728     
729     #ifdef __sparc_v9__
730     extern u32 tl0_solaris[8];
731     #define update_ttable(x) 										\
732     	tl0_solaris[3] = (((long)(x) - (long)tl0_solaris - 3) >> 2) | 0x40000000;			\
733     	__asm__ __volatile__ ("membar #StoreStore; flush %0" : : "r" (&tl0_solaris[3]))
734     #else
735     #endif	
736     
737     extern u32 solaris_sparc_syscall[];
738     extern u32 solaris_syscall[];
739     extern void cleanup_socksys(void);
740     
741     int init_module(void)
742     {
743     	int ret;
744     
745     	SOLDD(("Solaris module at %p\n", solaris_sparc_syscall));
746     	register_exec_domain(&solaris_exec_domain);
747     	if ((ret = init_socksys())) {
748     		unregister_exec_domain(&solaris_exec_domain);
749     		return ret;
750     	}
751     	update_ttable(solaris_sparc_syscall);
752     	return 0;
753     }
754     
755     void cleanup_module(void)
756     {
757     	update_ttable(solaris_syscall);
758     	cleanup_socksys();
759     	unregister_exec_domain(&solaris_exec_domain);
760     }
761     
762     #else
763     int init_solaris_emul(void)
764     {
765     	register_exec_domain(&solaris_exec_domain);
766     	init_socksys();
767     	return 0;
768     }
769     #endif
770     
771