diff options
author | Michal Simek <monstr@monstr.eu> | 2009-03-27 09:25:28 -0400 |
---|---|---|
committer | Michal Simek <monstr@monstr.eu> | 2009-03-27 09:25:28 -0400 |
commit | 7dcbbb2b17d4ef0d0541708eddfb720e2e422c3b (patch) | |
tree | 39607b2cde26579ac0b3357ff539f79012e58bf1 /arch/microblaze/kernel/sys_microblaze.c | |
parent | 2b4384542691fddd309f9324b5a9af976b75e918 (diff) |
microblaze_v8: IPC support
Reviewed-by: Ingo Molnar <mingo@elte.hu>
Acked-by: John Linn <john.linn@xilinx.com>
Acked-by: Stephen Neuendorffer <stephen.neuendorffer@xilinx.com>
Acked-by: John Williams <john.williams@petalogix.com>
Signed-off-by: Michal Simek <monstr@monstr.eu>
Diffstat (limited to 'arch/microblaze/kernel/sys_microblaze.c')
-rw-r--r-- | arch/microblaze/kernel/sys_microblaze.c | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/arch/microblaze/kernel/sys_microblaze.c b/arch/microblaze/kernel/sys_microblaze.c new file mode 100644 index 000000000000..d90b548fb1bb --- /dev/null +++ b/arch/microblaze/kernel/sys_microblaze.c | |||
@@ -0,0 +1,227 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007-2009 Michal Simek <monstr@monstr.eu> | ||
3 | * Copyright (C) 2007-2009 PetaLogix | ||
4 | * Copyright (C) 2007 John Williams <john.williams@petalogix.com> | ||
5 | * | ||
6 | * Copyright (C) 2006 Atmark Techno, Inc. | ||
7 | * Yasushi SHOJI <yashi@atmark-techno.com> | ||
8 | * Tetsuya OHKAWA <tetsuya@atmark-techno.com> | ||
9 | * | ||
10 | * This file is subject to the terms and conditions of the GNU General Public | ||
11 | * License. See the file "COPYING" in the main directory of this archive | ||
12 | * for more details. | ||
13 | */ | ||
14 | |||
15 | #include <linux/errno.h> | ||
16 | #include <linux/mm.h> | ||
17 | #include <linux/smp.h> | ||
18 | #include <linux/smp_lock.h> | ||
19 | #include <linux/syscalls.h> | ||
20 | #include <linux/sem.h> | ||
21 | #include <linux/msg.h> | ||
22 | #include <linux/shm.h> | ||
23 | #include <linux/stat.h> | ||
24 | #include <linux/mman.h> | ||
25 | #include <linux/sys.h> | ||
26 | #include <linux/ipc.h> | ||
27 | #include <linux/utsname.h> | ||
28 | #include <linux/file.h> | ||
29 | #include <linux/module.h> | ||
30 | #include <linux/err.h> | ||
31 | #include <linux/fs.h> | ||
32 | #include <linux/ipc.h> | ||
33 | #include <linux/semaphore.h> | ||
34 | #include <linux/syscalls.h> | ||
35 | #include <linux/uaccess.h> | ||
36 | #include <linux/unistd.h> | ||
37 | |||
38 | #include <asm/syscalls.h> | ||
39 | /* | ||
40 | * sys_ipc() is the de-multiplexer for the SysV IPC calls.. | ||
41 | * | ||
42 | * This is really horribly ugly. This will be remove with new toolchain. | ||
43 | */ | ||
44 | asmlinkage int | ||
45 | sys_ipc(uint call, int first, int second, int third, void *ptr, long fifth) | ||
46 | { | ||
47 | int version, ret; | ||
48 | |||
49 | version = call >> 16; /* hack for backward compatibility */ | ||
50 | call &= 0xffff; | ||
51 | |||
52 | ret = -EINVAL; | ||
53 | switch (call) { | ||
54 | case SEMOP: | ||
55 | ret = sys_semop(first, (struct sembuf *)ptr, second); | ||
56 | break; | ||
57 | case SEMGET: | ||
58 | ret = sys_semget(first, second, third); | ||
59 | break; | ||
60 | case SEMCTL: | ||
61 | { | ||
62 | union semun fourth; | ||
63 | |||
64 | if (!ptr) | ||
65 | break; | ||
66 | ret = (access_ok(VERIFY_READ, ptr, sizeof(long)) ? 0 : -EFAULT) | ||
67 | || (get_user(fourth.__pad, (void **)ptr)) ; | ||
68 | if (ret) | ||
69 | break; | ||
70 | ret = sys_semctl(first, second, third, fourth); | ||
71 | break; | ||
72 | } | ||
73 | case MSGSND: | ||
74 | ret = sys_msgsnd(first, (struct msgbuf *) ptr, second, third); | ||
75 | break; | ||
76 | case MSGRCV: | ||
77 | switch (version) { | ||
78 | case 0: { | ||
79 | struct ipc_kludge tmp; | ||
80 | |||
81 | if (!ptr) | ||
82 | break; | ||
83 | ret = (access_ok(VERIFY_READ, ptr, sizeof(tmp)) | ||
84 | ? 0 : -EFAULT) || copy_from_user(&tmp, | ||
85 | (struct ipc_kludge *) ptr, sizeof(tmp)); | ||
86 | if (ret) | ||
87 | break; | ||
88 | ret = sys_msgrcv(first, tmp.msgp, second, tmp.msgtyp, | ||
89 | third); | ||
90 | break; | ||
91 | } | ||
92 | default: | ||
93 | ret = sys_msgrcv(first, (struct msgbuf *) ptr, | ||
94 | second, fifth, third); | ||
95 | break; | ||
96 | } | ||
97 | break; | ||
98 | case MSGGET: | ||
99 | ret = sys_msgget((key_t) first, second); | ||
100 | break; | ||
101 | case MSGCTL: | ||
102 | ret = sys_msgctl(first, second, (struct msqid_ds *) ptr); | ||
103 | break; | ||
104 | case SHMAT: | ||
105 | switch (version) { | ||
106 | default: { | ||
107 | ulong raddr; | ||
108 | ret = access_ok(VERIFY_WRITE, (ulong *) third, | ||
109 | sizeof(ulong)) ? 0 : -EFAULT; | ||
110 | if (ret) | ||
111 | break; | ||
112 | ret = do_shmat(first, (char *) ptr, second, &raddr); | ||
113 | if (ret) | ||
114 | break; | ||
115 | ret = put_user(raddr, (ulong *) third); | ||
116 | break; | ||
117 | } | ||
118 | case 1: /* iBCS2 emulator entry point */ | ||
119 | if (!segment_eq(get_fs(), get_ds())) | ||
120 | break; | ||
121 | ret = do_shmat(first, (char *) ptr, second, | ||
122 | (ulong *) third); | ||
123 | break; | ||
124 | } | ||
125 | break; | ||
126 | case SHMDT: | ||
127 | ret = sys_shmdt((char *)ptr); | ||
128 | break; | ||
129 | case SHMGET: | ||
130 | ret = sys_shmget(first, second, third); | ||
131 | break; | ||
132 | case SHMCTL: | ||
133 | ret = sys_shmctl(first, second, (struct shmid_ds *) ptr); | ||
134 | break; | ||
135 | } | ||
136 | return -EINVAL; | ||
137 | } | ||
138 | |||
139 | asmlinkage int sys_vfork(struct pt_regs *regs) | ||
140 | { | ||
141 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->r1, | ||
142 | regs, 0, NULL, NULL); | ||
143 | } | ||
144 | |||
145 | asmlinkage int sys_clone(int flags, unsigned long stack, struct pt_regs *regs) | ||
146 | { | ||
147 | if (!stack) | ||
148 | stack = regs->r1; | ||
149 | return do_fork(flags, stack, regs, 0, NULL, NULL); | ||
150 | } | ||
151 | |||
152 | asmlinkage int sys_execve(char __user *filenamei, char __user *__user *argv, | ||
153 | char __user *__user *envp, struct pt_regs *regs) | ||
154 | { | ||
155 | int error; | ||
156 | char *filename; | ||
157 | |||
158 | filename = getname(filenamei); | ||
159 | error = PTR_ERR(filename); | ||
160 | if (IS_ERR(filename)) | ||
161 | goto out; | ||
162 | error = do_execve(filename, argv, envp, regs); | ||
163 | putname(filename); | ||
164 | out: | ||
165 | return error; | ||
166 | } | ||
167 | |||
168 | asmlinkage unsigned long | ||
169 | sys_mmap2(unsigned long addr, size_t len, | ||
170 | unsigned long prot, unsigned long flags, | ||
171 | unsigned long fd, unsigned long pgoff) | ||
172 | { | ||
173 | struct file *file = NULL; | ||
174 | int ret = -EBADF; | ||
175 | |||
176 | flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); | ||
177 | if (!(flags & MAP_ANONYMOUS)) { | ||
178 | file = fget(fd); | ||
179 | if (!file) { | ||
180 | printk(KERN_INFO "no fd in mmap\r\n"); | ||
181 | goto out; | ||
182 | } | ||
183 | } | ||
184 | |||
185 | down_write(¤t->mm->mmap_sem); | ||
186 | ret = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); | ||
187 | up_write(¤t->mm->mmap_sem); | ||
188 | if (file) | ||
189 | fput(file); | ||
190 | out: | ||
191 | return ret; | ||
192 | } | ||
193 | |||
194 | asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len, | ||
195 | unsigned long prot, unsigned long flags, | ||
196 | unsigned long fd, off_t offset) | ||
197 | { | ||
198 | int err = -EINVAL; | ||
199 | |||
200 | if (offset & ~PAGE_MASK) { | ||
201 | printk(KERN_INFO "no pagemask in mmap\r\n"); | ||
202 | goto out; | ||
203 | } | ||
204 | |||
205 | err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); | ||
206 | out: | ||
207 | return err; | ||
208 | } | ||
209 | |||
210 | /* | ||
211 | * Do a system call from kernel instead of calling sys_execve so we | ||
212 | * end up with proper pt_regs. | ||
213 | */ | ||
214 | int kernel_execve(const char *filename, char *const argv[], char *const envp[]) | ||
215 | { | ||
216 | register const char *__a __asm__("r5") = filename; | ||
217 | register const void *__b __asm__("r6") = argv; | ||
218 | register const void *__c __asm__("r7") = envp; | ||
219 | register unsigned long __syscall __asm__("r12") = __NR_execve; | ||
220 | register unsigned long __ret __asm__("r3"); | ||
221 | __asm__ __volatile__ ("brki r14, 0x8" | ||
222 | : "=r" (__ret), "=r" (__syscall) | ||
223 | : "1" (__syscall), "r" (__a), "r" (__b), "r" (__c) | ||
224 | : "r4", "r8", "r9", | ||
225 | "r10", "r11", "r14", "cc", "memory"); | ||
226 | return __ret; | ||
227 | } | ||