xref: /openbmc/linux/arch/mips/kernel/syscall.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1*1da177e4SLinus Torvalds /*
2*1da177e4SLinus Torvalds  * This file is subject to the terms and conditions of the GNU General Public
3*1da177e4SLinus Torvalds  * License.  See the file "COPYING" in the main directory of this archive
4*1da177e4SLinus Torvalds  * for more details.
5*1da177e4SLinus Torvalds  *
6*1da177e4SLinus Torvalds  * Copyright (C) 1995, 1996, 1997, 2000, 2001, 05 by Ralf Baechle
7*1da177e4SLinus Torvalds  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
8*1da177e4SLinus Torvalds  * Copyright (C) 2001 MIPS Technologies, Inc.
9*1da177e4SLinus Torvalds  */
10*1da177e4SLinus Torvalds #include <linux/a.out.h>
11*1da177e4SLinus Torvalds #include <linux/errno.h>
12*1da177e4SLinus Torvalds #include <linux/linkage.h>
13*1da177e4SLinus Torvalds #include <linux/mm.h>
14*1da177e4SLinus Torvalds #include <linux/smp.h>
15*1da177e4SLinus Torvalds #include <linux/smp_lock.h>
16*1da177e4SLinus Torvalds #include <linux/mman.h>
17*1da177e4SLinus Torvalds #include <linux/ptrace.h>
18*1da177e4SLinus Torvalds #include <linux/sched.h>
19*1da177e4SLinus Torvalds #include <linux/string.h>
20*1da177e4SLinus Torvalds #include <linux/syscalls.h>
21*1da177e4SLinus Torvalds #include <linux/file.h>
22*1da177e4SLinus Torvalds #include <linux/slab.h>
23*1da177e4SLinus Torvalds #include <linux/utsname.h>
24*1da177e4SLinus Torvalds #include <linux/unistd.h>
25*1da177e4SLinus Torvalds #include <linux/sem.h>
26*1da177e4SLinus Torvalds #include <linux/msg.h>
27*1da177e4SLinus Torvalds #include <linux/shm.h>
28*1da177e4SLinus Torvalds #include <linux/compiler.h>
29*1da177e4SLinus Torvalds 
30*1da177e4SLinus Torvalds #include <asm/branch.h>
31*1da177e4SLinus Torvalds #include <asm/cachectl.h>
32*1da177e4SLinus Torvalds #include <asm/cacheflush.h>
33*1da177e4SLinus Torvalds #include <asm/ipc.h>
34*1da177e4SLinus Torvalds #include <asm/offset.h>
35*1da177e4SLinus Torvalds #include <asm/signal.h>
36*1da177e4SLinus Torvalds #include <asm/sim.h>
37*1da177e4SLinus Torvalds #include <asm/shmparam.h>
38*1da177e4SLinus Torvalds #include <asm/sysmips.h>
39*1da177e4SLinus Torvalds #include <asm/uaccess.h>
40*1da177e4SLinus Torvalds 
41*1da177e4SLinus Torvalds asmlinkage int sys_pipe(nabi_no_regargs volatile struct pt_regs regs)
42*1da177e4SLinus Torvalds {
43*1da177e4SLinus Torvalds 	int fd[2];
44*1da177e4SLinus Torvalds 	int error, res;
45*1da177e4SLinus Torvalds 
46*1da177e4SLinus Torvalds 	error = do_pipe(fd);
47*1da177e4SLinus Torvalds 	if (error) {
48*1da177e4SLinus Torvalds 		res = error;
49*1da177e4SLinus Torvalds 		goto out;
50*1da177e4SLinus Torvalds 	}
51*1da177e4SLinus Torvalds 	regs.regs[3] = fd[1];
52*1da177e4SLinus Torvalds 	res = fd[0];
53*1da177e4SLinus Torvalds out:
54*1da177e4SLinus Torvalds 	return res;
55*1da177e4SLinus Torvalds }
56*1da177e4SLinus Torvalds 
57*1da177e4SLinus Torvalds unsigned long shm_align_mask = PAGE_SIZE - 1;	/* Sane caches */
58*1da177e4SLinus Torvalds 
59*1da177e4SLinus Torvalds #define COLOUR_ALIGN(addr,pgoff)				\
60*1da177e4SLinus Torvalds 	((((addr) + shm_align_mask) & ~shm_align_mask) +	\
61*1da177e4SLinus Torvalds 	 (((pgoff) << PAGE_SHIFT) & shm_align_mask))
62*1da177e4SLinus Torvalds 
63*1da177e4SLinus Torvalds unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
64*1da177e4SLinus Torvalds 	unsigned long len, unsigned long pgoff, unsigned long flags)
65*1da177e4SLinus Torvalds {
66*1da177e4SLinus Torvalds 	struct vm_area_struct * vmm;
67*1da177e4SLinus Torvalds 	int do_color_align;
68*1da177e4SLinus Torvalds 	unsigned long task_size;
69*1da177e4SLinus Torvalds 
70*1da177e4SLinus Torvalds 	task_size = STACK_TOP;
71*1da177e4SLinus Torvalds 
72*1da177e4SLinus Torvalds 	if (flags & MAP_FIXED) {
73*1da177e4SLinus Torvalds 		/*
74*1da177e4SLinus Torvalds 		 * We do not accept a shared mapping if it would violate
75*1da177e4SLinus Torvalds 		 * cache aliasing constraints.
76*1da177e4SLinus Torvalds 		 */
77*1da177e4SLinus Torvalds 		if ((flags & MAP_SHARED) && (addr & shm_align_mask))
78*1da177e4SLinus Torvalds 			return -EINVAL;
79*1da177e4SLinus Torvalds 		return addr;
80*1da177e4SLinus Torvalds 	}
81*1da177e4SLinus Torvalds 
82*1da177e4SLinus Torvalds 	if (len > task_size)
83*1da177e4SLinus Torvalds 		return -ENOMEM;
84*1da177e4SLinus Torvalds 	do_color_align = 0;
85*1da177e4SLinus Torvalds 	if (filp || (flags & MAP_SHARED))
86*1da177e4SLinus Torvalds 		do_color_align = 1;
87*1da177e4SLinus Torvalds 	if (addr) {
88*1da177e4SLinus Torvalds 		if (do_color_align)
89*1da177e4SLinus Torvalds 			addr = COLOUR_ALIGN(addr, pgoff);
90*1da177e4SLinus Torvalds 		else
91*1da177e4SLinus Torvalds 			addr = PAGE_ALIGN(addr);
92*1da177e4SLinus Torvalds 		vmm = find_vma(current->mm, addr);
93*1da177e4SLinus Torvalds 		if (task_size - len >= addr &&
94*1da177e4SLinus Torvalds 		    (!vmm || addr + len <= vmm->vm_start))
95*1da177e4SLinus Torvalds 			return addr;
96*1da177e4SLinus Torvalds 	}
97*1da177e4SLinus Torvalds 	addr = TASK_UNMAPPED_BASE;
98*1da177e4SLinus Torvalds 	if (do_color_align)
99*1da177e4SLinus Torvalds 		addr = COLOUR_ALIGN(addr, pgoff);
100*1da177e4SLinus Torvalds 	else
101*1da177e4SLinus Torvalds 		addr = PAGE_ALIGN(addr);
102*1da177e4SLinus Torvalds 
103*1da177e4SLinus Torvalds 	for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
104*1da177e4SLinus Torvalds 		/* At this point:  (!vmm || addr < vmm->vm_end). */
105*1da177e4SLinus Torvalds 		if (task_size - len < addr)
106*1da177e4SLinus Torvalds 			return -ENOMEM;
107*1da177e4SLinus Torvalds 		if (!vmm || addr + len <= vmm->vm_start)
108*1da177e4SLinus Torvalds 			return addr;
109*1da177e4SLinus Torvalds 		addr = vmm->vm_end;
110*1da177e4SLinus Torvalds 		if (do_color_align)
111*1da177e4SLinus Torvalds 			addr = COLOUR_ALIGN(addr, pgoff);
112*1da177e4SLinus Torvalds 	}
113*1da177e4SLinus Torvalds }
114*1da177e4SLinus Torvalds 
115*1da177e4SLinus Torvalds /* common code for old and new mmaps */
116*1da177e4SLinus Torvalds static inline unsigned long
117*1da177e4SLinus Torvalds do_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
118*1da177e4SLinus Torvalds         unsigned long flags, unsigned long fd, unsigned long pgoff)
119*1da177e4SLinus Torvalds {
120*1da177e4SLinus Torvalds 	unsigned long error = -EBADF;
121*1da177e4SLinus Torvalds 	struct file * file = NULL;
122*1da177e4SLinus Torvalds 
123*1da177e4SLinus Torvalds 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
124*1da177e4SLinus Torvalds 	if (!(flags & MAP_ANONYMOUS)) {
125*1da177e4SLinus Torvalds 		file = fget(fd);
126*1da177e4SLinus Torvalds 		if (!file)
127*1da177e4SLinus Torvalds 			goto out;
128*1da177e4SLinus Torvalds 	}
129*1da177e4SLinus Torvalds 
130*1da177e4SLinus Torvalds 	down_write(&current->mm->mmap_sem);
131*1da177e4SLinus Torvalds 	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
132*1da177e4SLinus Torvalds 	up_write(&current->mm->mmap_sem);
133*1da177e4SLinus Torvalds 
134*1da177e4SLinus Torvalds 	if (file)
135*1da177e4SLinus Torvalds 		fput(file);
136*1da177e4SLinus Torvalds out:
137*1da177e4SLinus Torvalds 	return error;
138*1da177e4SLinus Torvalds }
139*1da177e4SLinus Torvalds 
140*1da177e4SLinus Torvalds asmlinkage unsigned long
141*1da177e4SLinus Torvalds old_mmap(unsigned long addr, unsigned long len, int prot,
142*1da177e4SLinus Torvalds 	int flags, int fd, off_t offset)
143*1da177e4SLinus Torvalds {
144*1da177e4SLinus Torvalds 	unsigned long result;
145*1da177e4SLinus Torvalds 
146*1da177e4SLinus Torvalds 	result = -EINVAL;
147*1da177e4SLinus Torvalds 	if (offset & ~PAGE_MASK)
148*1da177e4SLinus Torvalds 		goto out;
149*1da177e4SLinus Torvalds 
150*1da177e4SLinus Torvalds 	result = do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
151*1da177e4SLinus Torvalds 
152*1da177e4SLinus Torvalds out:
153*1da177e4SLinus Torvalds 	return result;
154*1da177e4SLinus Torvalds }
155*1da177e4SLinus Torvalds 
156*1da177e4SLinus Torvalds asmlinkage unsigned long
157*1da177e4SLinus Torvalds sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
158*1da177e4SLinus Torvalds           unsigned long flags, unsigned long fd, unsigned long pgoff)
159*1da177e4SLinus Torvalds {
160*1da177e4SLinus Torvalds 	return do_mmap2(addr, len, prot, flags, fd, pgoff);
161*1da177e4SLinus Torvalds }
162*1da177e4SLinus Torvalds 
163*1da177e4SLinus Torvalds save_static_function(sys_fork);
164*1da177e4SLinus Torvalds __attribute_used__ noinline static int
165*1da177e4SLinus Torvalds _sys_fork(nabi_no_regargs struct pt_regs regs)
166*1da177e4SLinus Torvalds {
167*1da177e4SLinus Torvalds 	return do_fork(SIGCHLD, regs.regs[29], &regs, 0, NULL, NULL);
168*1da177e4SLinus Torvalds }
169*1da177e4SLinus Torvalds 
170*1da177e4SLinus Torvalds save_static_function(sys_clone);
171*1da177e4SLinus Torvalds __attribute_used__ noinline static int
172*1da177e4SLinus Torvalds _sys_clone(nabi_no_regargs struct pt_regs regs)
173*1da177e4SLinus Torvalds {
174*1da177e4SLinus Torvalds 	unsigned long clone_flags;
175*1da177e4SLinus Torvalds 	unsigned long newsp;
176*1da177e4SLinus Torvalds 	int *parent_tidptr, *child_tidptr;
177*1da177e4SLinus Torvalds 
178*1da177e4SLinus Torvalds 	clone_flags = regs.regs[4];
179*1da177e4SLinus Torvalds 	newsp = regs.regs[5];
180*1da177e4SLinus Torvalds 	if (!newsp)
181*1da177e4SLinus Torvalds 		newsp = regs.regs[29];
182*1da177e4SLinus Torvalds 	parent_tidptr = (int *) regs.regs[6];
183*1da177e4SLinus Torvalds 	child_tidptr = (int *) regs.regs[7];
184*1da177e4SLinus Torvalds 	return do_fork(clone_flags, newsp, &regs, 0,
185*1da177e4SLinus Torvalds 	               parent_tidptr, child_tidptr);
186*1da177e4SLinus Torvalds }
187*1da177e4SLinus Torvalds 
188*1da177e4SLinus Torvalds /*
189*1da177e4SLinus Torvalds  * sys_execve() executes a new program.
190*1da177e4SLinus Torvalds  */
191*1da177e4SLinus Torvalds asmlinkage int sys_execve(nabi_no_regargs struct pt_regs regs)
192*1da177e4SLinus Torvalds {
193*1da177e4SLinus Torvalds 	int error;
194*1da177e4SLinus Torvalds 	char * filename;
195*1da177e4SLinus Torvalds 
196*1da177e4SLinus Torvalds 	filename = getname((char *) (long)regs.regs[4]);
197*1da177e4SLinus Torvalds 	error = PTR_ERR(filename);
198*1da177e4SLinus Torvalds 	if (IS_ERR(filename))
199*1da177e4SLinus Torvalds 		goto out;
200*1da177e4SLinus Torvalds 	error = do_execve(filename, (char **) (long)regs.regs[5],
201*1da177e4SLinus Torvalds 	                  (char **) (long)regs.regs[6], &regs);
202*1da177e4SLinus Torvalds 	putname(filename);
203*1da177e4SLinus Torvalds 
204*1da177e4SLinus Torvalds out:
205*1da177e4SLinus Torvalds 	return error;
206*1da177e4SLinus Torvalds }
207*1da177e4SLinus Torvalds 
208*1da177e4SLinus Torvalds /*
209*1da177e4SLinus Torvalds  * Compacrapability ...
210*1da177e4SLinus Torvalds  */
211*1da177e4SLinus Torvalds asmlinkage int sys_uname(struct old_utsname * name)
212*1da177e4SLinus Torvalds {
213*1da177e4SLinus Torvalds 	if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
214*1da177e4SLinus Torvalds 		return 0;
215*1da177e4SLinus Torvalds 	return -EFAULT;
216*1da177e4SLinus Torvalds }
217*1da177e4SLinus Torvalds 
218*1da177e4SLinus Torvalds /*
219*1da177e4SLinus Torvalds  * Compacrapability ...
220*1da177e4SLinus Torvalds  */
221*1da177e4SLinus Torvalds asmlinkage int sys_olduname(struct oldold_utsname * name)
222*1da177e4SLinus Torvalds {
223*1da177e4SLinus Torvalds 	int error;
224*1da177e4SLinus Torvalds 
225*1da177e4SLinus Torvalds 	if (!name)
226*1da177e4SLinus Torvalds 		return -EFAULT;
227*1da177e4SLinus Torvalds 	if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
228*1da177e4SLinus Torvalds 		return -EFAULT;
229*1da177e4SLinus Torvalds 
230*1da177e4SLinus Torvalds 	error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
231*1da177e4SLinus Torvalds 	error -= __put_user(0,name->sysname+__OLD_UTS_LEN);
232*1da177e4SLinus Torvalds 	error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
233*1da177e4SLinus Torvalds 	error -= __put_user(0,name->nodename+__OLD_UTS_LEN);
234*1da177e4SLinus Torvalds 	error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
235*1da177e4SLinus Torvalds 	error -= __put_user(0,name->release+__OLD_UTS_LEN);
236*1da177e4SLinus Torvalds 	error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
237*1da177e4SLinus Torvalds 	error -= __put_user(0,name->version+__OLD_UTS_LEN);
238*1da177e4SLinus Torvalds 	error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
239*1da177e4SLinus Torvalds 	error = __put_user(0,name->machine+__OLD_UTS_LEN);
240*1da177e4SLinus Torvalds 	error = error ? -EFAULT : 0;
241*1da177e4SLinus Torvalds 
242*1da177e4SLinus Torvalds 	return error;
243*1da177e4SLinus Torvalds }
244*1da177e4SLinus Torvalds 
245*1da177e4SLinus Torvalds asmlinkage int _sys_sysmips(int cmd, long arg1, int arg2, int arg3)
246*1da177e4SLinus Torvalds {
247*1da177e4SLinus Torvalds 	int	tmp, len;
248*1da177e4SLinus Torvalds 	char	*name;
249*1da177e4SLinus Torvalds 
250*1da177e4SLinus Torvalds 	switch(cmd) {
251*1da177e4SLinus Torvalds 	case SETNAME: {
252*1da177e4SLinus Torvalds 		char nodename[__NEW_UTS_LEN + 1];
253*1da177e4SLinus Torvalds 
254*1da177e4SLinus Torvalds 		if (!capable(CAP_SYS_ADMIN))
255*1da177e4SLinus Torvalds 			return -EPERM;
256*1da177e4SLinus Torvalds 
257*1da177e4SLinus Torvalds 		name = (char *) arg1;
258*1da177e4SLinus Torvalds 
259*1da177e4SLinus Torvalds 		len = strncpy_from_user(nodename, name, __NEW_UTS_LEN);
260*1da177e4SLinus Torvalds 		if (len < 0)
261*1da177e4SLinus Torvalds 			return -EFAULT;
262*1da177e4SLinus Torvalds 
263*1da177e4SLinus Torvalds 		down_write(&uts_sem);
264*1da177e4SLinus Torvalds 		strncpy(system_utsname.nodename, nodename, len);
265*1da177e4SLinus Torvalds 		nodename[__NEW_UTS_LEN] = '\0';
266*1da177e4SLinus Torvalds 		strlcpy(system_utsname.nodename, nodename,
267*1da177e4SLinus Torvalds 		        sizeof(system_utsname.nodename));
268*1da177e4SLinus Torvalds 		up_write(&uts_sem);
269*1da177e4SLinus Torvalds 		return 0;
270*1da177e4SLinus Torvalds 	}
271*1da177e4SLinus Torvalds 
272*1da177e4SLinus Torvalds 	case MIPS_ATOMIC_SET:
273*1da177e4SLinus Torvalds 		printk(KERN_CRIT "How did I get here?\n");
274*1da177e4SLinus Torvalds 		return -EINVAL;
275*1da177e4SLinus Torvalds 
276*1da177e4SLinus Torvalds 	case MIPS_FIXADE:
277*1da177e4SLinus Torvalds 		tmp = current->thread.mflags & ~3;
278*1da177e4SLinus Torvalds 		current->thread.mflags = tmp | (arg1 & 3);
279*1da177e4SLinus Torvalds 		return 0;
280*1da177e4SLinus Torvalds 
281*1da177e4SLinus Torvalds 	case FLUSH_CACHE:
282*1da177e4SLinus Torvalds 		__flush_cache_all();
283*1da177e4SLinus Torvalds 		return 0;
284*1da177e4SLinus Torvalds 
285*1da177e4SLinus Torvalds 	case MIPS_RDNVRAM:
286*1da177e4SLinus Torvalds 		return -EIO;
287*1da177e4SLinus Torvalds 	}
288*1da177e4SLinus Torvalds 
289*1da177e4SLinus Torvalds 	return -EINVAL;
290*1da177e4SLinus Torvalds }
291*1da177e4SLinus Torvalds 
292*1da177e4SLinus Torvalds /*
293*1da177e4SLinus Torvalds  * sys_ipc() is the de-multiplexer for the SysV IPC calls..
294*1da177e4SLinus Torvalds  *
295*1da177e4SLinus Torvalds  * This is really horribly ugly.
296*1da177e4SLinus Torvalds  */
297*1da177e4SLinus Torvalds asmlinkage int sys_ipc (uint call, int first, int second,
298*1da177e4SLinus Torvalds 			unsigned long third, void *ptr, long fifth)
299*1da177e4SLinus Torvalds {
300*1da177e4SLinus Torvalds 	int version, ret;
301*1da177e4SLinus Torvalds 
302*1da177e4SLinus Torvalds 	version = call >> 16; /* hack for backward compatibility */
303*1da177e4SLinus Torvalds 	call &= 0xffff;
304*1da177e4SLinus Torvalds 
305*1da177e4SLinus Torvalds 	switch (call) {
306*1da177e4SLinus Torvalds 	case SEMOP:
307*1da177e4SLinus Torvalds 		return sys_semtimedop (first, (struct sembuf *)ptr, second,
308*1da177e4SLinus Torvalds 		                       NULL);
309*1da177e4SLinus Torvalds 	case SEMTIMEDOP:
310*1da177e4SLinus Torvalds 		return sys_semtimedop (first, (struct sembuf *)ptr, second,
311*1da177e4SLinus Torvalds 		                       (const struct timespec __user *)fifth);
312*1da177e4SLinus Torvalds 	case SEMGET:
313*1da177e4SLinus Torvalds 		return sys_semget (first, second, third);
314*1da177e4SLinus Torvalds 	case SEMCTL: {
315*1da177e4SLinus Torvalds 		union semun fourth;
316*1da177e4SLinus Torvalds 		if (!ptr)
317*1da177e4SLinus Torvalds 			return -EINVAL;
318*1da177e4SLinus Torvalds 		if (get_user(fourth.__pad, (void **) ptr))
319*1da177e4SLinus Torvalds 			return -EFAULT;
320*1da177e4SLinus Torvalds 		return sys_semctl (first, second, third, fourth);
321*1da177e4SLinus Torvalds 	}
322*1da177e4SLinus Torvalds 
323*1da177e4SLinus Torvalds 	case MSGSND:
324*1da177e4SLinus Torvalds 		return sys_msgsnd (first, (struct msgbuf *) ptr,
325*1da177e4SLinus Torvalds 				   second, third);
326*1da177e4SLinus Torvalds 	case MSGRCV:
327*1da177e4SLinus Torvalds 		switch (version) {
328*1da177e4SLinus Torvalds 		case 0: {
329*1da177e4SLinus Torvalds 			struct ipc_kludge tmp;
330*1da177e4SLinus Torvalds 			if (!ptr)
331*1da177e4SLinus Torvalds 				return -EINVAL;
332*1da177e4SLinus Torvalds 
333*1da177e4SLinus Torvalds 			if (copy_from_user(&tmp,
334*1da177e4SLinus Torvalds 					   (struct ipc_kludge *) ptr,
335*1da177e4SLinus Torvalds 					   sizeof (tmp)))
336*1da177e4SLinus Torvalds 				return -EFAULT;
337*1da177e4SLinus Torvalds 			return sys_msgrcv (first, tmp.msgp, second,
338*1da177e4SLinus Torvalds 					   tmp.msgtyp, third);
339*1da177e4SLinus Torvalds 		}
340*1da177e4SLinus Torvalds 		default:
341*1da177e4SLinus Torvalds 			return sys_msgrcv (first,
342*1da177e4SLinus Torvalds 					   (struct msgbuf *) ptr,
343*1da177e4SLinus Torvalds 					   second, fifth, third);
344*1da177e4SLinus Torvalds 		}
345*1da177e4SLinus Torvalds 	case MSGGET:
346*1da177e4SLinus Torvalds 		return sys_msgget ((key_t) first, second);
347*1da177e4SLinus Torvalds 	case MSGCTL:
348*1da177e4SLinus Torvalds 		return sys_msgctl (first, second, (struct msqid_ds *) ptr);
349*1da177e4SLinus Torvalds 
350*1da177e4SLinus Torvalds 	case SHMAT:
351*1da177e4SLinus Torvalds 		switch (version) {
352*1da177e4SLinus Torvalds 		default: {
353*1da177e4SLinus Torvalds 			ulong raddr;
354*1da177e4SLinus Torvalds 			ret = do_shmat (first, (char *) ptr, second, &raddr);
355*1da177e4SLinus Torvalds 			if (ret)
356*1da177e4SLinus Torvalds 				return ret;
357*1da177e4SLinus Torvalds 			return put_user (raddr, (ulong *) third);
358*1da177e4SLinus Torvalds 		}
359*1da177e4SLinus Torvalds 		case 1:	/* iBCS2 emulator entry point */
360*1da177e4SLinus Torvalds 			if (!segment_eq(get_fs(), get_ds()))
361*1da177e4SLinus Torvalds 				return -EINVAL;
362*1da177e4SLinus Torvalds 			return do_shmat (first, (char *) ptr, second, (ulong *) third);
363*1da177e4SLinus Torvalds 		}
364*1da177e4SLinus Torvalds 	case SHMDT:
365*1da177e4SLinus Torvalds 		return sys_shmdt ((char *)ptr);
366*1da177e4SLinus Torvalds 	case SHMGET:
367*1da177e4SLinus Torvalds 		return sys_shmget (first, second, third);
368*1da177e4SLinus Torvalds 	case SHMCTL:
369*1da177e4SLinus Torvalds 		return sys_shmctl (first, second,
370*1da177e4SLinus Torvalds 				   (struct shmid_ds *) ptr);
371*1da177e4SLinus Torvalds 	default:
372*1da177e4SLinus Torvalds 		return -ENOSYS;
373*1da177e4SLinus Torvalds 	}
374*1da177e4SLinus Torvalds }
375*1da177e4SLinus Torvalds 
376*1da177e4SLinus Torvalds /*
377*1da177e4SLinus Torvalds  * Native ABI that is O32 or N64 version
378*1da177e4SLinus Torvalds  */
379*1da177e4SLinus Torvalds asmlinkage long sys_shmat(int shmid, char __user *shmaddr,
380*1da177e4SLinus Torvalds                           int shmflg, unsigned long *addr)
381*1da177e4SLinus Torvalds {
382*1da177e4SLinus Torvalds 	unsigned long raddr;
383*1da177e4SLinus Torvalds 	int err;
384*1da177e4SLinus Torvalds 
385*1da177e4SLinus Torvalds 	err = do_shmat(shmid, shmaddr, shmflg, &raddr);
386*1da177e4SLinus Torvalds 	if (err)
387*1da177e4SLinus Torvalds 		return err;
388*1da177e4SLinus Torvalds 
389*1da177e4SLinus Torvalds 	return put_user(raddr, addr);
390*1da177e4SLinus Torvalds }
391*1da177e4SLinus Torvalds 
392*1da177e4SLinus Torvalds /*
393*1da177e4SLinus Torvalds  * No implemented yet ...
394*1da177e4SLinus Torvalds  */
395*1da177e4SLinus Torvalds asmlinkage int sys_cachectl(char *addr, int nbytes, int op)
396*1da177e4SLinus Torvalds {
397*1da177e4SLinus Torvalds 	return -ENOSYS;
398*1da177e4SLinus Torvalds }
399*1da177e4SLinus Torvalds 
400*1da177e4SLinus Torvalds /*
401*1da177e4SLinus Torvalds  * If we ever come here the user sp is bad.  Zap the process right away.
402*1da177e4SLinus Torvalds  * Due to the bad stack signaling wouldn't work.
403*1da177e4SLinus Torvalds  */
404*1da177e4SLinus Torvalds asmlinkage void bad_stack(void)
405*1da177e4SLinus Torvalds {
406*1da177e4SLinus Torvalds 	do_exit(SIGSEGV);
407*1da177e4SLinus Torvalds }
408