diff options
author | Sam Ravnborg <sam@ravnborg.org> | 2008-12-03 06:08:37 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-12-04 12:17:20 -0500 |
commit | d670bd4f803c8b646acd20f3ba21e65458293faf (patch) | |
tree | eabc30aadce1556023c4aa445c649ba9e1d3f352 /arch/sparc/kernel/sys_sparc.c | |
parent | 478b8fecda511942404ac232897a718cecd13e48 (diff) |
sparc: prepare kernel/ for unification
o sparc32 files with identical names to sparc64 renamed to <name>_32.S
o introduced a few Kconfig helpers to simplify Makefile logic
o refactored Makefile to prepare for unification
- use obj-$(CONFIG_SPARC32) for sparc32 specific files
- use <name>_$(BITS) for files where sparc64 has a _64 variant
- sparc64 directly include a few files where sparc32 builds them,
refer to these files directly (no BITS)
- sneaked in -Werror as used by sparc64
o modified sparc/Makefile to use the new names for head/init_task
Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc/kernel/sys_sparc.c')
-rw-r--r-- | arch/sparc/kernel/sys_sparc.c | 466 |
1 files changed, 0 insertions, 466 deletions
diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c deleted file mode 100644 index 03035c852a43..000000000000 --- a/arch/sparc/kernel/sys_sparc.c +++ /dev/null | |||
@@ -1,466 +0,0 @@ | |||
1 | /* linux/arch/sparc/kernel/sys_sparc.c | ||
2 | * | ||
3 | * This file contains various random system calls that | ||
4 | * have a non-standard calling sequence on the Linux/sparc | ||
5 | * platform. | ||
6 | */ | ||
7 | |||
8 | #include <linux/errno.h> | ||
9 | #include <linux/types.h> | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/mm.h> | ||
12 | #include <linux/fs.h> | ||
13 | #include <linux/file.h> | ||
14 | #include <linux/sem.h> | ||
15 | #include <linux/msg.h> | ||
16 | #include <linux/shm.h> | ||
17 | #include <linux/stat.h> | ||
18 | #include <linux/syscalls.h> | ||
19 | #include <linux/mman.h> | ||
20 | #include <linux/utsname.h> | ||
21 | #include <linux/smp.h> | ||
22 | #include <linux/smp_lock.h> | ||
23 | #include <linux/ipc.h> | ||
24 | |||
25 | #include <asm/uaccess.h> | ||
26 | #include <asm/unistd.h> | ||
27 | |||
28 | /* #define DEBUG_UNIMP_SYSCALL */ | ||
29 | |||
30 | /* XXX Make this per-binary type, this way we can detect the type of | ||
31 | * XXX a binary. Every Sparc executable calls this very early on. | ||
32 | */ | ||
33 | asmlinkage unsigned long sys_getpagesize(void) | ||
34 | { | ||
35 | return PAGE_SIZE; /* Possibly older binaries want 8192 on sun4's? */ | ||
36 | } | ||
37 | |||
38 | #define COLOUR_ALIGN(addr) (((addr)+SHMLBA-1)&~(SHMLBA-1)) | ||
39 | |||
40 | unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) | ||
41 | { | ||
42 | struct vm_area_struct * vmm; | ||
43 | |||
44 | if (flags & MAP_FIXED) { | ||
45 | /* We do not accept a shared mapping if it would violate | ||
46 | * cache aliasing constraints. | ||
47 | */ | ||
48 | if ((flags & MAP_SHARED) && (addr & (SHMLBA - 1))) | ||
49 | return -EINVAL; | ||
50 | return addr; | ||
51 | } | ||
52 | |||
53 | /* See asm-sparc/uaccess.h */ | ||
54 | if (len > TASK_SIZE - PAGE_SIZE) | ||
55 | return -ENOMEM; | ||
56 | if (ARCH_SUN4C && len > 0x20000000) | ||
57 | return -ENOMEM; | ||
58 | if (!addr) | ||
59 | addr = TASK_UNMAPPED_BASE; | ||
60 | |||
61 | if (flags & MAP_SHARED) | ||
62 | addr = COLOUR_ALIGN(addr); | ||
63 | else | ||
64 | addr = PAGE_ALIGN(addr); | ||
65 | |||
66 | for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) { | ||
67 | /* At this point: (!vmm || addr < vmm->vm_end). */ | ||
68 | if (ARCH_SUN4C && addr < 0xe0000000 && 0x20000000 - len < addr) { | ||
69 | addr = PAGE_OFFSET; | ||
70 | vmm = find_vma(current->mm, PAGE_OFFSET); | ||
71 | } | ||
72 | if (TASK_SIZE - PAGE_SIZE - len < addr) | ||
73 | return -ENOMEM; | ||
74 | if (!vmm || addr + len <= vmm->vm_start) | ||
75 | return addr; | ||
76 | addr = vmm->vm_end; | ||
77 | if (flags & MAP_SHARED) | ||
78 | addr = COLOUR_ALIGN(addr); | ||
79 | } | ||
80 | } | ||
81 | |||
82 | asmlinkage unsigned long sparc_brk(unsigned long brk) | ||
83 | { | ||
84 | if(ARCH_SUN4C) { | ||
85 | if ((brk & 0xe0000000) != (current->mm->brk & 0xe0000000)) | ||
86 | return current->mm->brk; | ||
87 | } | ||
88 | return sys_brk(brk); | ||
89 | } | ||
90 | |||
91 | /* | ||
92 | * sys_pipe() is the normal C calling standard for creating | ||
93 | * a pipe. It's not the way unix traditionally does this, though. | ||
94 | */ | ||
95 | asmlinkage int sparc_pipe(struct pt_regs *regs) | ||
96 | { | ||
97 | int fd[2]; | ||
98 | int error; | ||
99 | |||
100 | error = do_pipe_flags(fd, 0); | ||
101 | if (error) | ||
102 | goto out; | ||
103 | regs->u_regs[UREG_I1] = fd[1]; | ||
104 | error = fd[0]; | ||
105 | out: | ||
106 | return error; | ||
107 | } | ||
108 | |||
109 | /* | ||
110 | * sys_ipc() is the de-multiplexer for the SysV IPC calls.. | ||
111 | * | ||
112 | * This is really horribly ugly. | ||
113 | */ | ||
114 | |||
115 | asmlinkage int sys_ipc (uint call, int first, int second, int third, void __user *ptr, long fifth) | ||
116 | { | ||
117 | int version, err; | ||
118 | |||
119 | version = call >> 16; /* hack for backward compatibility */ | ||
120 | call &= 0xffff; | ||
121 | |||
122 | if (call <= SEMCTL) | ||
123 | switch (call) { | ||
124 | case SEMOP: | ||
125 | err = sys_semtimedop (first, (struct sembuf __user *)ptr, second, NULL); | ||
126 | goto out; | ||
127 | case SEMTIMEDOP: | ||
128 | err = sys_semtimedop (first, (struct sembuf __user *)ptr, second, (const struct timespec __user *) fifth); | ||
129 | goto out; | ||
130 | case SEMGET: | ||
131 | err = sys_semget (first, second, third); | ||
132 | goto out; | ||
133 | case SEMCTL: { | ||
134 | union semun fourth; | ||
135 | err = -EINVAL; | ||
136 | if (!ptr) | ||
137 | goto out; | ||
138 | err = -EFAULT; | ||
139 | if (get_user(fourth.__pad, | ||
140 | (void __user * __user *)ptr)) | ||
141 | goto out; | ||
142 | err = sys_semctl (first, second, third, fourth); | ||
143 | goto out; | ||
144 | } | ||
145 | default: | ||
146 | err = -ENOSYS; | ||
147 | goto out; | ||
148 | } | ||
149 | if (call <= MSGCTL) | ||
150 | switch (call) { | ||
151 | case MSGSND: | ||
152 | err = sys_msgsnd (first, (struct msgbuf __user *) ptr, | ||
153 | second, third); | ||
154 | goto out; | ||
155 | case MSGRCV: | ||
156 | switch (version) { | ||
157 | case 0: { | ||
158 | struct ipc_kludge tmp; | ||
159 | err = -EINVAL; | ||
160 | if (!ptr) | ||
161 | goto out; | ||
162 | err = -EFAULT; | ||
163 | if (copy_from_user(&tmp, (struct ipc_kludge __user *) ptr, sizeof (tmp))) | ||
164 | goto out; | ||
165 | err = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third); | ||
166 | goto out; | ||
167 | } | ||
168 | case 1: default: | ||
169 | err = sys_msgrcv (first, | ||
170 | (struct msgbuf __user *) ptr, | ||
171 | second, fifth, third); | ||
172 | goto out; | ||
173 | } | ||
174 | case MSGGET: | ||
175 | err = sys_msgget ((key_t) first, second); | ||
176 | goto out; | ||
177 | case MSGCTL: | ||
178 | err = sys_msgctl (first, second, (struct msqid_ds __user *) ptr); | ||
179 | goto out; | ||
180 | default: | ||
181 | err = -ENOSYS; | ||
182 | goto out; | ||
183 | } | ||
184 | if (call <= SHMCTL) | ||
185 | switch (call) { | ||
186 | case SHMAT: | ||
187 | switch (version) { | ||
188 | case 0: default: { | ||
189 | ulong raddr; | ||
190 | err = do_shmat (first, (char __user *) ptr, second, &raddr); | ||
191 | if (err) | ||
192 | goto out; | ||
193 | err = -EFAULT; | ||
194 | if (put_user (raddr, (ulong __user *) third)) | ||
195 | goto out; | ||
196 | err = 0; | ||
197 | goto out; | ||
198 | } | ||
199 | case 1: /* iBCS2 emulator entry point */ | ||
200 | err = -EINVAL; | ||
201 | goto out; | ||
202 | } | ||
203 | case SHMDT: | ||
204 | err = sys_shmdt ((char __user *)ptr); | ||
205 | goto out; | ||
206 | case SHMGET: | ||
207 | err = sys_shmget (first, second, third); | ||
208 | goto out; | ||
209 | case SHMCTL: | ||
210 | err = sys_shmctl (first, second, (struct shmid_ds __user *) ptr); | ||
211 | goto out; | ||
212 | default: | ||
213 | err = -ENOSYS; | ||
214 | goto out; | ||
215 | } | ||
216 | else | ||
217 | err = -ENOSYS; | ||
218 | out: | ||
219 | return err; | ||
220 | } | ||
221 | |||
222 | int sparc_mmap_check(unsigned long addr, unsigned long len) | ||
223 | { | ||
224 | if (ARCH_SUN4C && | ||
225 | (len > 0x20000000 || | ||
226 | (addr < 0xe0000000 && addr + len > 0x20000000))) | ||
227 | return -EINVAL; | ||
228 | |||
229 | /* See asm-sparc/uaccess.h */ | ||
230 | if (len > TASK_SIZE - PAGE_SIZE || addr + len > TASK_SIZE - PAGE_SIZE) | ||
231 | return -EINVAL; | ||
232 | |||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | /* Linux version of mmap */ | ||
237 | static unsigned long do_mmap2(unsigned long addr, unsigned long len, | ||
238 | unsigned long prot, unsigned long flags, unsigned long fd, | ||
239 | unsigned long pgoff) | ||
240 | { | ||
241 | struct file * file = NULL; | ||
242 | unsigned long retval = -EBADF; | ||
243 | |||
244 | if (!(flags & MAP_ANONYMOUS)) { | ||
245 | file = fget(fd); | ||
246 | if (!file) | ||
247 | goto out; | ||
248 | } | ||
249 | |||
250 | len = PAGE_ALIGN(len); | ||
251 | flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); | ||
252 | |||
253 | down_write(¤t->mm->mmap_sem); | ||
254 | retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); | ||
255 | up_write(¤t->mm->mmap_sem); | ||
256 | |||
257 | if (file) | ||
258 | fput(file); | ||
259 | out: | ||
260 | return retval; | ||
261 | } | ||
262 | |||
263 | asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len, | ||
264 | unsigned long prot, unsigned long flags, unsigned long fd, | ||
265 | unsigned long pgoff) | ||
266 | { | ||
267 | /* Make sure the shift for mmap2 is constant (12), no matter what PAGE_SIZE | ||
268 | we have. */ | ||
269 | return do_mmap2(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT - 12)); | ||
270 | } | ||
271 | |||
272 | asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len, | ||
273 | unsigned long prot, unsigned long flags, unsigned long fd, | ||
274 | unsigned long off) | ||
275 | { | ||
276 | return do_mmap2(addr, len, prot, flags, fd, off >> PAGE_SHIFT); | ||
277 | } | ||
278 | |||
279 | long sparc_remap_file_pages(unsigned long start, unsigned long size, | ||
280 | unsigned long prot, unsigned long pgoff, | ||
281 | unsigned long flags) | ||
282 | { | ||
283 | /* This works on an existing mmap so we don't need to validate | ||
284 | * the range as that was done at the original mmap call. | ||
285 | */ | ||
286 | return sys_remap_file_pages(start, size, prot, | ||
287 | (pgoff >> (PAGE_SHIFT - 12)), flags); | ||
288 | } | ||
289 | |||
290 | extern unsigned long do_mremap(unsigned long addr, | ||
291 | unsigned long old_len, unsigned long new_len, | ||
292 | unsigned long flags, unsigned long new_addr); | ||
293 | |||
294 | asmlinkage unsigned long sparc_mremap(unsigned long addr, | ||
295 | unsigned long old_len, unsigned long new_len, | ||
296 | unsigned long flags, unsigned long new_addr) | ||
297 | { | ||
298 | unsigned long ret = -EINVAL; | ||
299 | |||
300 | if (unlikely(sparc_mmap_check(addr, old_len))) | ||
301 | goto out; | ||
302 | if (unlikely(sparc_mmap_check(new_addr, new_len))) | ||
303 | goto out; | ||
304 | down_write(¤t->mm->mmap_sem); | ||
305 | ret = do_mremap(addr, old_len, new_len, flags, new_addr); | ||
306 | up_write(¤t->mm->mmap_sem); | ||
307 | out: | ||
308 | return ret; | ||
309 | } | ||
310 | |||
311 | /* we come to here via sys_nis_syscall so it can setup the regs argument */ | ||
312 | asmlinkage unsigned long | ||
313 | c_sys_nis_syscall (struct pt_regs *regs) | ||
314 | { | ||
315 | static int count = 0; | ||
316 | |||
317 | if (count++ > 5) | ||
318 | return -ENOSYS; | ||
319 | printk ("%s[%d]: Unimplemented SPARC system call %d\n", | ||
320 | current->comm, task_pid_nr(current), (int)regs->u_regs[1]); | ||
321 | #ifdef DEBUG_UNIMP_SYSCALL | ||
322 | show_regs (regs); | ||
323 | #endif | ||
324 | return -ENOSYS; | ||
325 | } | ||
326 | |||
327 | /* #define DEBUG_SPARC_BREAKPOINT */ | ||
328 | |||
329 | asmlinkage void | ||
330 | sparc_breakpoint (struct pt_regs *regs) | ||
331 | { | ||
332 | siginfo_t info; | ||
333 | |||
334 | lock_kernel(); | ||
335 | #ifdef DEBUG_SPARC_BREAKPOINT | ||
336 | printk ("TRAP: Entering kernel PC=%x, nPC=%x\n", regs->pc, regs->npc); | ||
337 | #endif | ||
338 | info.si_signo = SIGTRAP; | ||
339 | info.si_errno = 0; | ||
340 | info.si_code = TRAP_BRKPT; | ||
341 | info.si_addr = (void __user *)regs->pc; | ||
342 | info.si_trapno = 0; | ||
343 | force_sig_info(SIGTRAP, &info, current); | ||
344 | |||
345 | #ifdef DEBUG_SPARC_BREAKPOINT | ||
346 | printk ("TRAP: Returning to space: PC=%x nPC=%x\n", regs->pc, regs->npc); | ||
347 | #endif | ||
348 | unlock_kernel(); | ||
349 | } | ||
350 | |||
351 | asmlinkage int | ||
352 | sparc_sigaction (int sig, const struct old_sigaction __user *act, | ||
353 | struct old_sigaction __user *oact) | ||
354 | { | ||
355 | struct k_sigaction new_ka, old_ka; | ||
356 | int ret; | ||
357 | |||
358 | WARN_ON_ONCE(sig >= 0); | ||
359 | sig = -sig; | ||
360 | |||
361 | if (act) { | ||
362 | unsigned long mask; | ||
363 | |||
364 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || | ||
365 | __get_user(new_ka.sa.sa_handler, &act->sa_handler) || | ||
366 | __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) | ||
367 | return -EFAULT; | ||
368 | __get_user(new_ka.sa.sa_flags, &act->sa_flags); | ||
369 | __get_user(mask, &act->sa_mask); | ||
370 | siginitset(&new_ka.sa.sa_mask, mask); | ||
371 | new_ka.ka_restorer = NULL; | ||
372 | } | ||
373 | |||
374 | ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); | ||
375 | |||
376 | if (!ret && oact) { | ||
377 | /* In the clone() case we could copy half consistent | ||
378 | * state to the user, however this could sleep and | ||
379 | * deadlock us if we held the signal lock on SMP. So for | ||
380 | * now I take the easy way out and do no locking. | ||
381 | */ | ||
382 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || | ||
383 | __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || | ||
384 | __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) | ||
385 | return -EFAULT; | ||
386 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags); | ||
387 | __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); | ||
388 | } | ||
389 | |||
390 | return ret; | ||
391 | } | ||
392 | |||
393 | asmlinkage long | ||
394 | sys_rt_sigaction(int sig, | ||
395 | const struct sigaction __user *act, | ||
396 | struct sigaction __user *oact, | ||
397 | void __user *restorer, | ||
398 | size_t sigsetsize) | ||
399 | { | ||
400 | struct k_sigaction new_ka, old_ka; | ||
401 | int ret; | ||
402 | |||
403 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
404 | if (sigsetsize != sizeof(sigset_t)) | ||
405 | return -EINVAL; | ||
406 | |||
407 | if (act) { | ||
408 | new_ka.ka_restorer = restorer; | ||
409 | if (copy_from_user(&new_ka.sa, act, sizeof(*act))) | ||
410 | return -EFAULT; | ||
411 | } | ||
412 | |||
413 | ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); | ||
414 | |||
415 | if (!ret && oact) { | ||
416 | if (copy_to_user(oact, &old_ka.sa, sizeof(*oact))) | ||
417 | return -EFAULT; | ||
418 | } | ||
419 | |||
420 | return ret; | ||
421 | } | ||
422 | |||
423 | asmlinkage int sys_getdomainname(char __user *name, int len) | ||
424 | { | ||
425 | int nlen, err; | ||
426 | |||
427 | if (len < 0) | ||
428 | return -EINVAL; | ||
429 | |||
430 | down_read(&uts_sem); | ||
431 | |||
432 | nlen = strlen(utsname()->domainname) + 1; | ||
433 | err = -EINVAL; | ||
434 | if (nlen > len) | ||
435 | goto out; | ||
436 | |||
437 | err = -EFAULT; | ||
438 | if (!copy_to_user(name, utsname()->domainname, nlen)) | ||
439 | err = 0; | ||
440 | |||
441 | out: | ||
442 | up_read(&uts_sem); | ||
443 | return err; | ||
444 | } | ||
445 | |||
446 | /* | ||
447 | * Do a system call from kernel instead of calling sys_execve so we | ||
448 | * end up with proper pt_regs. | ||
449 | */ | ||
450 | int kernel_execve(const char *filename, char *const argv[], char *const envp[]) | ||
451 | { | ||
452 | long __res; | ||
453 | register long __g1 __asm__ ("g1") = __NR_execve; | ||
454 | register long __o0 __asm__ ("o0") = (long)(filename); | ||
455 | register long __o1 __asm__ ("o1") = (long)(argv); | ||
456 | register long __o2 __asm__ ("o2") = (long)(envp); | ||
457 | asm volatile ("t 0x10\n\t" | ||
458 | "bcc 1f\n\t" | ||
459 | "mov %%o0, %0\n\t" | ||
460 | "sub %%g0, %%o0, %0\n\t" | ||
461 | "1:\n\t" | ||
462 | : "=r" (__res), "=&r" (__o0) | ||
463 | : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1) | ||
464 | : "cc"); | ||
465 | return __res; | ||
466 | } | ||