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 
do_solaris_mmap(u32 addr,u32 len,u32 prot,u32 flags,u32 fd,u64 off)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;
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 
solaris_mmap(u32 addr,u32 len,u32 prot,u32 flags,u32 fd,u32 off)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 
solaris_mmap64(struct pt_regs * regs,u32 len,u32 prot,u32 flags,u32 fd,u32 offhi)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 
solaris_brk(u32 brk)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 
machine(void)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 
platform(char * buffer)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 
serial(char * buffer)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 
solaris_utssys(u32 buf,u32 flags,int which,u32 buf2)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 
solaris_utsname(u32 buf)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 
solaris_sysinfo(int cmd,u32 buf,s32 count)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 
solaris_sysconf(int id)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 
solaris_procids(int cmd,s32 pid,s32 pgid)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 
solaris_gettimeofday(u32 tim)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 
solaris_getrlimit(unsigned int resource,struct rlimit32 * rlim)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 
solaris_setrlimit(unsigned int resource,struct rlimit32 * rlim)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 
solaris_getrlimit64(unsigned int resource,struct rlimit * rlim)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 
solaris_setrlimit64(unsigned int resource,struct rlimit * rlim)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 
solaris_ntp_gettime(struct sol_ntptimeval * ntp)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 
solaris_ntp_adjtime(struct sol_timex * txp)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 
do_sol_unimplemented(struct pt_regs * regs)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 
solaris_register(void)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 MODULE_LICENSE("GPL");
728 EXPORT_NO_SYMBOLS;
729 
730 #ifdef __sparc_v9__
731 extern u32 tl0_solaris[8];
732 #define update_ttable(x) 										\
733 	tl0_solaris[3] = (((long)(x) - (long)tl0_solaris - 3) >> 2) | 0x40000000;			\
734 	__asm__ __volatile__ ("membar #StoreStore; flush %0" : : "r" (&tl0_solaris[3]))
735 #else
736 #endif
737 
738 extern u32 solaris_sparc_syscall[];
739 extern u32 solaris_syscall[];
740 extern void cleanup_socksys(void);
741 
init_module(void)742 int init_module(void)
743 {
744 	int ret;
745 
746 	SOLDD(("Solaris module at %p\n", solaris_sparc_syscall));
747 	register_exec_domain(&solaris_exec_domain);
748 	if ((ret = init_socksys())) {
749 		unregister_exec_domain(&solaris_exec_domain);
750 		return ret;
751 	}
752 	update_ttable(solaris_sparc_syscall);
753 	return 0;
754 }
755 
cleanup_module(void)756 void cleanup_module(void)
757 {
758 	update_ttable(solaris_syscall);
759 	cleanup_socksys();
760 	unregister_exec_domain(&solaris_exec_domain);
761 }
762 
763 #else
init_solaris_emul(void)764 int init_solaris_emul(void)
765 {
766 	register_exec_domain(&solaris_exec_domain);
767 	init_socksys();
768 	return 0;
769 }
770 #endif
771 
772