Add a generic implementation of the old mmap() syscall, which expects its argument in a memory block and switch all architectures over to use it. Signed-off-by: Christoph Hellwig <hch@lst.de> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Paul Mundt <lethal@linux-sh.org> Cc: Jeff Dike <jdike@addtoit.com> Cc: Hirokazu Takata <takata@linux-m32r.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Ingo Molnar <mingo@elte.hu> Reviewed-by: H. Peter Anvin <hpa@zytor.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Heiko Carstens <heiko.carstens@de.ibm.com> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: "Luck, Tony" <tony.luck@intel.com> Cc: James Morris <jmorris@namei.org> Cc: Andreas Schwab <schwab@linux-m68k.org> Acked-by: Jesper Nilsson <jesper.nilsson@axis.com> Acked-by: Russell King <rmk+kernel@arm.linux.org.uk> Acked-by: Greg Ungerer <gerg@uclinux.org> Acked-by: David Howells <dhowells@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
179 lines
3.9 KiB
C
179 lines
3.9 KiB
C
/*
|
|
* linux/arch/m68knommu/kernel/sys_m68k.c
|
|
*
|
|
* This file contains various random system calls that
|
|
* have a non-standard calling sequence on the Linux/m68k
|
|
* platform.
|
|
*/
|
|
|
|
#include <linux/errno.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/smp.h>
|
|
#include <linux/sem.h>
|
|
#include <linux/msg.h>
|
|
#include <linux/shm.h>
|
|
#include <linux/stat.h>
|
|
#include <linux/syscalls.h>
|
|
#include <linux/mman.h>
|
|
#include <linux/file.h>
|
|
#include <linux/ipc.h>
|
|
#include <linux/fs.h>
|
|
|
|
#include <asm/setup.h>
|
|
#include <asm/uaccess.h>
|
|
#include <asm/cachectl.h>
|
|
#include <asm/traps.h>
|
|
#include <asm/cacheflush.h>
|
|
#include <asm/unistd.h>
|
|
|
|
/*
|
|
* sys_ipc() is the de-multiplexer for the SysV IPC calls..
|
|
*
|
|
* This is really horribly ugly.
|
|
*/
|
|
asmlinkage int sys_ipc (uint call, int first, int second,
|
|
int third, void *ptr, long fifth)
|
|
{
|
|
int version, ret;
|
|
|
|
version = call >> 16; /* hack for backward compatibility */
|
|
call &= 0xffff;
|
|
|
|
if (call <= SEMCTL)
|
|
switch (call) {
|
|
case SEMOP:
|
|
return sys_semop (first, (struct sembuf *)ptr, second);
|
|
case SEMGET:
|
|
return sys_semget (first, second, third);
|
|
case SEMCTL: {
|
|
union semun fourth;
|
|
if (!ptr)
|
|
return -EINVAL;
|
|
if (get_user(fourth.__pad, (void **) ptr))
|
|
return -EFAULT;
|
|
return sys_semctl (first, second, third, fourth);
|
|
}
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
if (call <= MSGCTL)
|
|
switch (call) {
|
|
case MSGSND:
|
|
return sys_msgsnd (first, (struct msgbuf *) ptr,
|
|
second, third);
|
|
case MSGRCV:
|
|
switch (version) {
|
|
case 0: {
|
|
struct ipc_kludge tmp;
|
|
if (!ptr)
|
|
return -EINVAL;
|
|
if (copy_from_user (&tmp,
|
|
(struct ipc_kludge *)ptr,
|
|
sizeof (tmp)))
|
|
return -EFAULT;
|
|
return sys_msgrcv (first, tmp.msgp, second,
|
|
tmp.msgtyp, third);
|
|
}
|
|
default:
|
|
return sys_msgrcv (first,
|
|
(struct msgbuf *) ptr,
|
|
second, fifth, third);
|
|
}
|
|
case MSGGET:
|
|
return sys_msgget ((key_t) first, second);
|
|
case MSGCTL:
|
|
return sys_msgctl (first, second,
|
|
(struct msqid_ds *) ptr);
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
if (call <= SHMCTL)
|
|
switch (call) {
|
|
case SHMAT:
|
|
switch (version) {
|
|
default: {
|
|
ulong raddr;
|
|
ret = do_shmat (first, ptr, second, &raddr);
|
|
if (ret)
|
|
return ret;
|
|
return put_user (raddr, (ulong __user *) third);
|
|
}
|
|
}
|
|
case SHMDT:
|
|
return sys_shmdt (ptr);
|
|
case SHMGET:
|
|
return sys_shmget (first, second, third);
|
|
case SHMCTL:
|
|
return sys_shmctl (first, second, ptr);
|
|
default:
|
|
return -ENOSYS;
|
|
}
|
|
|
|
return -EINVAL;
|
|
}
|
|
|
|
/* sys_cacheflush -- flush (part of) the processor cache. */
|
|
asmlinkage int
|
|
sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
|
|
{
|
|
flush_cache_all();
|
|
return(0);
|
|
}
|
|
|
|
asmlinkage int sys_getpagesize(void)
|
|
{
|
|
return PAGE_SIZE;
|
|
}
|
|
|
|
/*
|
|
* Do a system call from kernel instead of calling sys_execve so we
|
|
* end up with proper pt_regs.
|
|
*/
|
|
int kernel_execve(const char *filename, char *const argv[], char *const envp[])
|
|
{
|
|
register long __res asm ("%d0") = __NR_execve;
|
|
register long __a asm ("%d1") = (long)(filename);
|
|
register long __b asm ("%d2") = (long)(argv);
|
|
register long __c asm ("%d3") = (long)(envp);
|
|
asm volatile ("trap #0" : "+d" (__res)
|
|
: "d" (__a), "d" (__b), "d" (__c));
|
|
return __res;
|
|
}
|
|
|
|
asmlinkage unsigned long sys_get_thread_area(void)
|
|
{
|
|
return current_thread_info()->tp_value;
|
|
}
|
|
|
|
asmlinkage int sys_set_thread_area(unsigned long tp)
|
|
{
|
|
current_thread_info()->tp_value = tp;
|
|
return 0;
|
|
}
|
|
|
|
/* This syscall gets its arguments in A0 (mem), D2 (oldval) and
|
|
D1 (newval). */
|
|
asmlinkage int
|
|
sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5,
|
|
unsigned long __user * mem)
|
|
{
|
|
struct mm_struct *mm = current->mm;
|
|
unsigned long mem_value;
|
|
|
|
down_read(&mm->mmap_sem);
|
|
|
|
mem_value = *mem;
|
|
if (mem_value == oldval)
|
|
*mem = newval;
|
|
|
|
up_read(&mm->mmap_sem);
|
|
return mem_value;
|
|
}
|
|
|
|
asmlinkage int sys_atomic_barrier(void)
|
|
{
|
|
/* no code needed for uniprocs */
|
|
return 0;
|
|
}
|