sys_s390.c 5.6 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 *  arch/s390/kernel/sys_s390.c
 *
 *  S390 version
 *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
 *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
 *               Thomas Spatzier (tspat@de.ibm.com)
 *
 *  Derived from "arch/i386/kernel/sys_i386.c"
 *
 *  This file contains various random system calls that
 *  have a non-standard calling sequence on the Linux/s390
 *  platform.
 */

#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/mm.h>
A
Alexey Dobriyan 已提交
19
#include <linux/fs.h>
L
Linus Torvalds 已提交
20 21 22 23 24 25 26 27 28 29
#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/utsname.h>
#include <linux/personality.h>
30
#include <linux/unistd.h>
A
Adrian Bunk 已提交
31
#include <linux/ipc.h>
L
Linus Torvalds 已提交
32
#include <asm/uaccess.h>
33
#include "entry.h"
L
Linus Torvalds 已提交
34 35

/*
C
Christoph Hellwig 已提交
36 37 38
 * Perform the mmap() system call. Linux for S/390 isn't able to handle more
 * than 5 system call parameters, so this system call uses a memory block
 * for parameter passing.
L
Linus Torvalds 已提交
39 40
 */

C
Christoph Hellwig 已提交
41
struct s390_mmap_arg_struct {
L
Linus Torvalds 已提交
42 43 44 45 46 47 48 49
	unsigned long addr;
	unsigned long len;
	unsigned long prot;
	unsigned long flags;
	unsigned long fd;
	unsigned long offset;
};

C
Christoph Hellwig 已提交
50
SYSCALL_DEFINE1(mmap2, struct s390_mmap_arg_struct __user *, arg)
L
Linus Torvalds 已提交
51
{
C
Christoph Hellwig 已提交
52
	struct s390_mmap_arg_struct a;
L
Linus Torvalds 已提交
53 54 55 56
	int error = -EFAULT;

	if (copy_from_user(&a, arg, sizeof(a)))
		goto out;
A
Al Viro 已提交
57
	error = sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
L
Linus Torvalds 已提交
58 59 60 61 62 63 64 65 66
out:
	return error;
}

/*
 * sys_ipc() is the de-multiplexer for the SysV IPC calls..
 *
 * This is really horribly ugly.
 */
C
Christoph Hellwig 已提交
67
SYSCALL_DEFINE5(s390_ipc, uint, call, int, first, unsigned long, second,
68
		unsigned long, third, void __user *, ptr)
L
Linus Torvalds 已提交
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
{
        struct ipc_kludge tmp;
	int ret;

        switch (call) {
        case SEMOP:
		return sys_semtimedop(first, (struct sembuf __user *)ptr,
				       (unsigned)second, NULL);
	case SEMTIMEDOP:
		return sys_semtimedop(first, (struct sembuf __user *)ptr,
				       (unsigned)second,
				       (const struct timespec __user *) third);
        case SEMGET:
                return sys_semget(first, (int)second, third);
        case SEMCTL: {
                union semun fourth;
                if (!ptr)
                        return -EINVAL;
                if (get_user(fourth.__pad, (void __user * __user *) ptr))
                        return -EFAULT;
                return sys_semctl(first, (int)second, third, fourth);
        }
        case MSGSND:
		return sys_msgsnd (first, (struct msgbuf __user *) ptr,
                                   (size_t)second, third);
		break;
        case MSGRCV:
                if (!ptr)
                        return -EINVAL;
                if (copy_from_user (&tmp, (struct ipc_kludge __user *) ptr,
                                    sizeof (struct ipc_kludge)))
                        return -EFAULT;
                return sys_msgrcv (first, tmp.msgp,
                                   (size_t)second, tmp.msgtyp, third);
        case MSGGET:
                return sys_msgget((key_t)first, (int)second);
        case MSGCTL:
                return sys_msgctl(first, (int)second,
				   (struct msqid_ds __user *)ptr);

	case SHMAT: {
		ulong raddr;
		ret = do_shmat(first, (char __user *)ptr,
				(int)second, &raddr);
		if (ret)
			return ret;
		return put_user (raddr, (ulong __user *) third);
		break;
        }
	case SHMDT:
		return sys_shmdt ((char __user *)ptr);
	case SHMGET:
		return sys_shmget(first, (size_t)second, third);
	case SHMCTL:
		return sys_shmctl(first, (int)second,
                                   (struct shmid_ds __user *) ptr);
	default:
		return -ENOSYS;

	}

	return -EINVAL;
}

133
#ifdef CONFIG_64BIT
134
SYSCALL_DEFINE1(s390_personality, unsigned long, personality)
L
Linus Torvalds 已提交
135 136 137 138 139 140 141 142 143 144 145
{
	int ret;

	if (current->personality == PER_LINUX32 && personality == PER_LINUX)
		personality = PER_LINUX32;
	ret = sys_personality(personality);
	if (ret == PER_LINUX32)
		ret = PER_LINUX;

	return ret;
}
146
#endif /* CONFIG_64BIT */
L
Linus Torvalds 已提交
147 148 149 150

/*
 * Wrapper function for sys_fadvise64/fadvise64_64
 */
151
#ifndef CONFIG_64BIT
L
Linus Torvalds 已提交
152

153 154
SYSCALL_DEFINE5(s390_fadvise64, int, fd, u32, offset_high, u32, offset_low,
		size_t, len, int, advice)
L
Linus Torvalds 已提交
155 156 157 158 159 160 161 162 163 164 165 166
{
	return sys_fadvise64(fd, (u64) offset_high << 32 | offset_low,
			len, advice);
}

struct fadvise64_64_args {
	int fd;
	long long offset;
	long long len;
	int advice;
};

167
SYSCALL_DEFINE1(s390_fadvise64_64, struct fadvise64_64_args __user *, args)
L
Linus Torvalds 已提交
168 169 170 171 172 173 174
{
	struct fadvise64_64_args a;

	if ( copy_from_user(&a, args, sizeof(a)) )
		return -EFAULT;
	return sys_fadvise64_64(a.fd, a.offset, a.len, a.advice);
}
175 176 177 178 179 180 181 182 183 184 185 186 187

/*
 * This is a wrapper to call sys_fallocate(). For 31 bit s390 the last
 * 64 bit argument "len" is split into the upper and lower 32 bits. The
 * system call wrapper in the user space loads the value to %r6/%r7.
 * The code in entry.S keeps the values in %r2 - %r6 where they are and
 * stores %r7 to 96(%r15). But the standard C linkage requires that
 * the whole 64 bit value for len is stored on the stack and doesn't
 * use %r6 at all. So s390_fallocate has to convert the arguments from
 *   %r2: fd, %r3: mode, %r4/%r5: offset, %r6/96(%r15)-99(%r15): len
 * to
 *   %r2: fd, %r3: mode, %r4/%r5: offset, 96(%r15)-103(%r15): len
 */
188
SYSCALL_DEFINE(s390_fallocate)(int fd, int mode, loff_t offset,
189 190 191 192
			       u32 len_high, u32 len_low)
{
	return sys_fallocate(fd, mode, offset, ((u64)len_high << 32) | len_low);
}
193 194 195 196 197 198 199 200 201 202
#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
asmlinkage long SyS_s390_fallocate(long fd, long mode, loff_t offset,
				   long len_high, long len_low)
{
	return SYSC_s390_fallocate((int) fd, (int) mode, offset,
				   (u32) len_high, (u32) len_low);
}
SYSCALL_ALIAS(sys_s390_fallocate, SyS_s390_fallocate);
#endif

203
#endif