1/*
2 * BK Id: SCCS/s.syscalls.c 1.13 03/13/02 09:12:22 trini
3 */
4/*
5 * linux/arch/ppc/kernel/sys_ppc.c
6 *
7 *  PowerPC version
8 *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
9 *
10 * Derived from "arch/i386/kernel/sys_i386.c"
11 * Adapted from the i386 version by Gary Thomas
12 * Modified by Cort Dougan (cort@cs.nmt.edu)
13 * and Paul Mackerras (paulus@cs.anu.edu.au).
14 *
15 * This file contains various random system calls that
16 * have a non-standard calling sequence on the Linux/PPC
17 * platform.
18 *
19 *  This program is free software; you can redistribute it and/or
20 *  modify it under the terms of the GNU General Public License
21 *  as published by the Free Software Foundation; either version
22 *  2 of the License, or (at your option) any later version.
23 *
24 */
25
26#include <linux/config.h>
27#include <linux/errno.h>
28#include <linux/sched.h>
29#include <linux/mm.h>
30#include <linux/smp.h>
31#include <linux/smp_lock.h>
32#include <linux/sem.h>
33#include <linux/msg.h>
34#include <linux/shm.h>
35#include <linux/stat.h>
36#include <linux/mman.h>
37#include <linux/sys.h>
38#include <linux/ipc.h>
39#include <linux/utsname.h>
40#include <linux/file.h>
41
42#include <asm/uaccess.h>
43#include <asm/ipc.h>
44#include <asm/semaphore.h>
45
46void
47check_bugs(void)
48{
49}
50
51int sys_ioperm(unsigned long from, unsigned long num, int on)
52{
53	printk(KERN_ERR "sys_ioperm()\n");
54	return -EIO;
55}
56
57int sys_iopl(int a1, int a2, int a3, int a4)
58{
59	printk(KERN_ERR "sys_iopl(%x, %x, %x, %x)!\n", a1, a2, a3, a4);
60	return (-ENOSYS);
61}
62
63int sys_vm86(int a1, int a2, int a3, int a4)
64{
65	printk(KERN_ERR "sys_vm86(%x, %x, %x, %x)!\n", a1, a2, a3, a4);
66	return (-ENOSYS);
67}
68
69int sys_modify_ldt(int a1, int a2, int a3, int a4)
70{
71	printk(KERN_ERR "sys_modify_ldt(%x, %x, %x, %x)!\n", a1, a2, a3, a4);
72	return (-ENOSYS);
73}
74
75/*
76 * sys_ipc() is the de-multiplexer for the SysV IPC calls..
77 *
78 * This is really horribly ugly.
79 */
80int
81sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
82{
83	int version, ret;
84
85	version = call >> 16; /* hack for backward compatibility */
86	call &= 0xffff;
87
88	ret = -EINVAL;
89	switch (call) {
90	case SEMOP:
91		ret = sys_semop (first, (struct sembuf *)ptr, second);
92		break;
93	case SEMGET:
94		ret = sys_semget (first, second, third);
95		break;
96	case SEMCTL: {
97		union semun fourth;
98
99		if (!ptr)
100			break;
101		if ((ret = verify_area (VERIFY_READ, ptr, sizeof(long)))
102		    || (ret = get_user(fourth.__pad, (void **)ptr)))
103			break;
104		ret = sys_semctl (first, second, third, fourth);
105		break;
106		}
107	case MSGSND:
108		ret = sys_msgsnd (first, (struct msgbuf *) ptr, second, third);
109		break;
110	case MSGRCV:
111		switch (version) {
112		case 0: {
113			struct ipc_kludge tmp;
114
115			if (!ptr)
116				break;
117			if ((ret = verify_area (VERIFY_READ, ptr, sizeof(tmp)))
118			    || (ret = copy_from_user(&tmp,
119						(struct ipc_kludge *) ptr,
120						sizeof (tmp))))
121				break;
122			ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp,
123					  third);
124			break;
125			}
126		default:
127			ret = sys_msgrcv (first, (struct msgbuf *) ptr,
128					  second, fifth, third);
129			break;
130		}
131		break;
132	case MSGGET:
133		ret = sys_msgget ((key_t) first, second);
134		break;
135	case MSGCTL:
136		ret = sys_msgctl (first, second, (struct msqid_ds *) ptr);
137		break;
138	case SHMAT:
139		switch (version) {
140		default: {
141			ulong raddr;
142
143			if ((ret = verify_area(VERIFY_WRITE, (ulong*) third,
144					       sizeof(ulong))))
145				break;
146			ret = sys_shmat (first, (char *) ptr, second, &raddr);
147			if (ret)
148				break;
149			ret = put_user (raddr, (ulong *) third);
150			break;
151			}
152		case 1:	/* iBCS2 emulator entry point */
153			if (!segment_eq(get_fs(), get_ds()))
154				break;
155			ret = sys_shmat (first, (char *) ptr, second,
156					 (ulong *) third);
157			break;
158		}
159		break;
160	case SHMDT:
161		ret = sys_shmdt ((char *)ptr);
162		break;
163	case SHMGET:
164		ret = sys_shmget (first, second, third);
165		break;
166	case SHMCTL:
167		ret = sys_shmctl (first, second, (struct shmid_ds *) ptr);
168		break;
169	}
170
171	return ret;
172}
173
174/*
175 * sys_pipe() is the normal C calling standard for creating
176 * a pipe. It's not the way unix traditionally does this, though.
177 */
178int sys_pipe(int *fildes)
179{
180	int fd[2];
181	int error;
182
183	error = do_pipe(fd);
184	if (!error) {
185		if (copy_to_user(fildes, fd, 2*sizeof(int)))
186			error = -EFAULT;
187	}
188	return error;
189}
190
191static inline unsigned long
192do_mmap2(unsigned long addr, size_t len,
193	 unsigned long prot, unsigned long flags,
194	 unsigned long fd, unsigned long pgoff)
195{
196	struct file * file = NULL;
197	int ret = -EBADF;
198
199	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
200	if (!(flags & MAP_ANONYMOUS)) {
201		if (!(file = fget(fd)))
202			goto out;
203	}
204
205	down_write(&current->mm->mmap_sem);
206	ret = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
207	up_write(&current->mm->mmap_sem);
208	if (file)
209		fput(file);
210out:
211	return ret;
212}
213
214unsigned long sys_mmap2(unsigned long addr, size_t len,
215			unsigned long prot, unsigned long flags,
216			unsigned long fd, unsigned long pgoff)
217{
218	return do_mmap2(addr, len, prot, flags, fd, pgoff);
219}
220
221unsigned long sys_mmap(unsigned long addr, size_t len,
222		       unsigned long prot, unsigned long flags,
223		       unsigned long fd, off_t offset)
224{
225	int err = -EINVAL;
226	unsigned long off = offset;
227
228	if (offset & ~PAGE_MASK)
229		goto out;
230
231	err = do_mmap2(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
232out:
233	return err;
234}
235
236extern int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
237
238/*
239 * Due to some executables calling the wrong select we sometimes
240 * get wrong args.  This determines how the args are being passed
241 * (a single ptr to them all args passed) then calls
242 * sys_select() with the appropriate args. -- Cort
243 */
244int
245ppc_select(int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval *tvp)
246{
247	if ( (unsigned long)n >= 4096 )
248	{
249		unsigned long *buffer = (unsigned long *)n;
250		if (verify_area(VERIFY_READ, buffer, 5*sizeof(unsigned long))
251		    || __get_user(n, buffer)
252		    || __get_user(inp, ((fd_set **)(buffer+1)))
253		    || __get_user(outp, ((fd_set **)(buffer+2)))
254		    || __get_user(exp, ((fd_set **)(buffer+3)))
255		    || __get_user(tvp, ((struct timeval **)(buffer+4))))
256			return -EFAULT;
257	}
258	return sys_select(n, inp, outp, exp, tvp);
259}
260
261int sys_pause(void)
262{
263	current->state = TASK_INTERRUPTIBLE;
264	schedule();
265	return -ERESTARTNOHAND;
266}
267
268int sys_uname(struct old_utsname * name)
269{
270	int err = -EFAULT;
271
272	down_read(&uts_sem);
273	if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
274		err = 0;
275	up_read(&uts_sem);
276	return err;
277}
278
279int sys_olduname(struct oldold_utsname * name)
280{
281	int error;
282
283	if (!name)
284		return -EFAULT;
285	if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
286		return -EFAULT;
287
288	down_read(&uts_sem);
289	error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
290	error -= __put_user(0,name->sysname+__OLD_UTS_LEN);
291	error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
292	error -= __put_user(0,name->nodename+__OLD_UTS_LEN);
293	error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
294	error -= __put_user(0,name->release+__OLD_UTS_LEN);
295	error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
296	error -= __put_user(0,name->version+__OLD_UTS_LEN);
297	error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
298	error = __put_user(0,name->machine+__OLD_UTS_LEN);
299	up_read(&uts_sem);
300
301	error = error ? -EFAULT : 0;
302	return error;
303}
304
305#ifndef CONFIG_PCI
306/*
307 * Those are normally defined in arch/ppc/kernel/pci.c. But when CONFIG_PCI is
308 * not defined, this file is not linked at all, so here are the "empty" versions
309 */
310int sys_pciconfig_read(void) { return -ENOSYS; }
311int sys_pciconfig_write(void) { return -ENOSYS; }
312long sys_pciconfig_iobase(void) { return -ENOSYS; }
313#endif
314