Root/target/linux/ubicom32/files/arch/ubicom32/kernel/sys_ubicom32.c

1/*
2 * arch/ubicom32/kernel/sys_ubicom32.c
3 * Ubicom32 architecture system call support implementation.
4 *
5 * (C) Copyright 2009, Ubicom, Inc.
6 *
7 * This file is part of the Ubicom32 Linux Kernel Port.
8 *
9 * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10 * it and/or modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation, either version 2 of the
12 * License, or (at your option) any later version.
13 *
14 * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with the Ubicom32 Linux Kernel Port. If not,
21 * see <http://www.gnu.org/licenses/>.
22 *
23 * Ubicom32 implementation derived from (with many thanks):
24 * arch/m68knommu
25 * arch/blackfin
26 * arch/parisc
27 *
28 * This file contains various random system calls that
29 * have a non-standard calling sequence on the Linux/ubicom32
30 * platform.
31 */
32
33#include <linux/module.h>
34#include <linux/errno.h>
35#include <linux/sched.h>
36#include <linux/mm.h>
37#include <linux/smp.h>
38#include <linux/sem.h>
39#include <linux/msg.h>
40#include <linux/shm.h>
41#include <linux/stat.h>
42#include <linux/syscalls.h>
43#include <linux/mman.h>
44#include <linux/file.h>
45#include <linux/utsname.h>
46#include <linux/ipc.h>
47#include <linux/fs.h>
48#include <linux/uaccess.h>
49#include <linux/unistd.h>
50
51#include <asm/setup.h>
52#include <asm/traps.h>
53#include <asm/cacheflush.h>
54
55/* common code for old and new mmaps */
56static inline long do_mmap2(
57    unsigned long addr, unsigned long len,
58    unsigned long prot, unsigned long flags,
59    unsigned long fd, unsigned long pgoff)
60{
61    int error = -EBADF;
62    struct file *file = NULL;
63
64    flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
65    if (!(flags & MAP_ANONYMOUS)) {
66        file = fget(fd);
67        if (!file)
68            goto out;
69    }
70
71    down_write(&current->mm->mmap_sem);
72    error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
73    up_write(&current->mm->mmap_sem);
74
75    if (file)
76        fput(file);
77out:
78    return error;
79}
80
81asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
82    unsigned long prot, unsigned long flags,
83    unsigned long fd, unsigned long pgoff)
84{
85    return do_mmap2(addr, len, prot, flags, fd, pgoff);
86}
87
88/*
89 * Perform the select(nd, in, out, ex, tv) and mmap() system
90 * calls. Linux/m68k cloned Linux/i386, which didn't use to be able to
91 * handle more than 4 system call parameters, so these system calls
92 * used a memory block for parameter passing..
93 */
94
95struct mmap_arg_struct {
96    unsigned long addr;
97    unsigned long len;
98    unsigned long prot;
99    unsigned long flags;
100    unsigned long fd;
101    unsigned long offset;
102};
103
104asmlinkage int old_mmap(struct mmap_arg_struct *arg)
105{
106    struct mmap_arg_struct a;
107    int error = -EFAULT;
108
109    if (copy_from_user(&a, arg, sizeof(a)))
110        goto out;
111
112    error = -EINVAL;
113    if (a.offset & ~PAGE_MASK)
114        goto out;
115
116    a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
117
118    error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd,
119             a.offset >> PAGE_SHIFT);
120out:
121    return error;
122}
123
124struct sel_arg_struct {
125    unsigned long n;
126    fd_set *inp, *outp, *exp;
127    struct timeval *tvp;
128};
129
130asmlinkage int old_select(struct sel_arg_struct *arg)
131{
132    struct sel_arg_struct a;
133
134    if (copy_from_user(&a, arg, sizeof(a)))
135        return -EFAULT;
136    /* sys_select() does the appropriate kernel locking */
137    return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
138}
139
140/*
141 * sys_ipc() is the de-multiplexer for the SysV IPC calls..
142 *
143 * This is really horribly ugly.
144 */
145asmlinkage int sys_ipc(uint call, int first, int second,
146            int third, void *ptr, long fifth)
147{
148    int version, ret;
149
150    version = call >> 16; /* hack for backward compatibility */
151    call &= 0xffff;
152
153    if (call <= SEMCTL)
154        switch (call) {
155        case SEMOP:
156            return sys_semop(first, (struct sembuf *)ptr, second);
157        case SEMGET:
158            return sys_semget(first, second, third);
159        case SEMCTL: {
160            union semun fourth;
161            if (!ptr)
162                return -EINVAL;
163            if (get_user(fourth.__pad, (void **) ptr))
164                return -EFAULT;
165            return sys_semctl(first, second, third, fourth);
166            }
167        default:
168            return -EINVAL;
169        }
170    if (call <= MSGCTL)
171        switch (call) {
172        case MSGSND:
173            return sys_msgsnd(first, (struct msgbuf *) ptr,
174                      second, third);
175        case MSGRCV:
176            switch (version) {
177            case 0: {
178                struct ipc_kludge tmp;
179                if (!ptr)
180                    return -EINVAL;
181                if (copy_from_user(&tmp,
182                           (struct ipc_kludge *)ptr,
183                           sizeof(tmp)))
184                    return -EFAULT;
185                return sys_msgrcv(first, tmp.msgp, second,
186                           tmp.msgtyp, third);
187                }
188            default:
189                return sys_msgrcv(first,
190                          (struct msgbuf *) ptr,
191                          second, fifth, third);
192            }
193        case MSGGET:
194            return sys_msgget((key_t) first, second);
195        case MSGCTL:
196            return sys_msgctl(first, second,
197                       (struct msqid_ds *) ptr);
198        default:
199            return -EINVAL;
200        }
201    if (call <= SHMCTL)
202        switch (call) {
203        case SHMAT:
204            switch (version) {
205            default: {
206                ulong raddr;
207                ret = do_shmat(first, ptr, second, &raddr);
208                if (ret)
209                    return ret;
210                return put_user(raddr, (ulong __user *) third);
211            }
212            }
213        case SHMDT:
214            return sys_shmdt(ptr);
215        case SHMGET:
216            return sys_shmget(first, second, third);
217        case SHMCTL:
218            return sys_shmctl(first, second, ptr);
219        default:
220            return -ENOSYS;
221        }
222
223    return -EINVAL;
224}
225
226/* sys_cacheflush -- flush (part of) the processor cache. */
227asmlinkage int
228sys_cacheflush(unsigned long addr, int scope, int cache, unsigned long len)
229{
230    flush_cache_all();
231    return 0;
232}
233
234asmlinkage int sys_getpagesize(void)
235{
236    return PAGE_SIZE;
237}
238

Archive Download this file



interactive