1
2
3
4
5
6
7
8
9#include <linux/errno.h>
10#include <linux/types.h>
11#include <linux/sched.h>
12#include <linux/mm.h>
13#include <linux/fs.h>
14#include <linux/file.h>
15#include <linux/sem.h>
16#include <linux/msg.h>
17#include <linux/shm.h>
18#include <linux/stat.h>
19#include <linux/syscalls.h>
20#include <linux/mman.h>
21#include <linux/utsname.h>
22#include <linux/smp.h>
23#include <linux/smp_lock.h>
24#include <linux/ipc.h>
25
26#include <asm/uaccess.h>
27#include <asm/unistd.h>
28
29
30
31
32
33
34asmlinkage unsigned long sys_getpagesize(void)
35{
36 return PAGE_SIZE;
37}
38
39#define COLOUR_ALIGN(addr) (((addr)+SHMLBA-1)&~(SHMLBA-1))
40
41unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags)
42{
43 struct vm_area_struct * vmm;
44
45 if (flags & MAP_FIXED) {
46
47
48
49 if ((flags & MAP_SHARED) && (addr & (SHMLBA - 1)))
50 return -EINVAL;
51 return addr;
52 }
53
54
55 if (len > TASK_SIZE - PAGE_SIZE)
56 return -ENOMEM;
57 if (ARCH_SUN4C_SUN4 && len > 0x20000000)
58 return -ENOMEM;
59 if (!addr)
60 addr = TASK_UNMAPPED_BASE;
61
62 if (flags & MAP_SHARED)
63 addr = COLOUR_ALIGN(addr);
64 else
65 addr = PAGE_ALIGN(addr);
66
67 for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
68
69 if (ARCH_SUN4C_SUN4 && addr < 0xe0000000 && 0x20000000 - len < addr) {
70 addr = PAGE_OFFSET;
71 vmm = find_vma(current->mm, PAGE_OFFSET);
72 }
73 if (TASK_SIZE - PAGE_SIZE - len < addr)
74 return -ENOMEM;
75 if (!vmm || addr + len <= vmm->vm_start)
76 return addr;
77 addr = vmm->vm_end;
78 if (flags & MAP_SHARED)
79 addr = COLOUR_ALIGN(addr);
80 }
81}
82
83asmlinkage unsigned long sparc_brk(unsigned long brk)
84{
85 if(ARCH_SUN4C_SUN4) {
86 if ((brk & 0xe0000000) != (current->mm->brk & 0xe0000000))
87 return current->mm->brk;
88 }
89 return sys_brk(brk);
90}
91
92
93
94
95
96asmlinkage int sparc_pipe(struct pt_regs *regs)
97{
98 int fd[2];
99 int error;
100
101 error = do_pipe(fd);
102 if (error)
103 goto out;
104 regs->u_regs[UREG_I1] = fd[1];
105 error = fd[0];
106out:
107 return error;
108}
109
110
111
112
113
114
115
116asmlinkage int sys_ipc (uint call, int first, int second, int third, void __user *ptr, long fifth)
117{
118 int version, err;
119
120 version = call >> 16;
121 call &= 0xffff;
122
123 if (call <= SEMCTL)
124 switch (call) {
125 case SEMOP:
126 err = sys_semtimedop (first, (struct sembuf __user *)ptr, second, NULL);
127 goto out;
128 case SEMTIMEDOP:
129 err = sys_semtimedop (first, (struct sembuf __user *)ptr, second, (const struct timespec __user *) fifth);
130 goto out;
131 case SEMGET:
132 err = sys_semget (first, second, third);
133 goto out;
134 case SEMCTL: {
135 union semun fourth;
136 err = -EINVAL;
137 if (!ptr)
138 goto out;
139 err = -EFAULT;
140 if (get_user(fourth.__pad,
141 (void __user * __user *)ptr))
142 goto out;
143 err = sys_semctl (first, second, third, fourth);
144 goto out;
145 }
146 default:
147 err = -ENOSYS;
148 goto out;
149 }
150 if (call <= MSGCTL)
151 switch (call) {
152 case MSGSND:
153 err = sys_msgsnd (first, (struct msgbuf __user *) ptr,
154 second, third);
155 goto out;
156 case MSGRCV:
157 switch (version) {
158 case 0: {
159 struct ipc_kludge tmp;
160 err = -EINVAL;
161 if (!ptr)
162 goto out;
163 err = -EFAULT;
164 if (copy_from_user(&tmp, (struct ipc_kludge __user *) ptr, sizeof (tmp)))
165 goto out;
166 err = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
167 goto out;
168 }
169 case 1: default:
170 err = sys_msgrcv (first,
171 (struct msgbuf __user *) ptr,
172 second, fifth, third);
173 goto out;
174 }
175 case MSGGET:
176 err = sys_msgget ((key_t) first, second);
177 goto out;
178 case MSGCTL:
179 err = sys_msgctl (first, second, (struct msqid_ds __user *) ptr);
180 goto out;
181 default:
182 err = -ENOSYS;
183 goto out;
184 }
185 if (call <= SHMCTL)
186 switch (call) {
187 case SHMAT:
188 switch (version) {
189 case 0: default: {
190 ulong raddr;
191 err = do_shmat (first, (char __user *) ptr, second, &raddr);
192 if (err)
193 goto out;
194 err = -EFAULT;
195 if (put_user (raddr, (ulong __user *) third))
196 goto out;
197 err = 0;
198 goto out;
199 }
200 case 1:
201 err = -EINVAL;
202 goto out;
203 }
204 case SHMDT:
205 err = sys_shmdt ((char __user *)ptr);
206 goto out;
207 case SHMGET:
208 err = sys_shmget (first, second, third);
209 goto out;
210 case SHMCTL:
211 err = sys_shmctl (first, second, (struct shmid_ds __user *) ptr);
212 goto out;
213 default:
214 err = -ENOSYS;
215 goto out;
216 }
217 else
218 err = -ENOSYS;
219out:
220 return err;
221}
222
223int sparc_mmap_check(unsigned long addr, unsigned long len)
224{
225 if (ARCH_SUN4C_SUN4 &&
226 (len > 0x20000000 ||
227 (addr < 0xe0000000 && addr + len > 0x20000000)))
228 return -EINVAL;
229
230
231 if (len > TASK_SIZE - PAGE_SIZE || addr + len > TASK_SIZE - PAGE_SIZE)
232 return -EINVAL;
233
234 return 0;
235}
236
237
238static unsigned long do_mmap2(unsigned long addr, unsigned long len,
239 unsigned long prot, unsigned long flags, unsigned long fd,
240 unsigned long pgoff)
241{
242 struct file * file = NULL;
243 unsigned long retval = -EBADF;
244
245 if (!(flags & MAP_ANONYMOUS)) {
246 file = fget(fd);
247 if (!file)
248 goto out;
249 }
250
251 len = PAGE_ALIGN(len);
252 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
253
254 down_write(¤t->mm->mmap_sem);
255 retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
256 up_write(¤t->mm->mmap_sem);
257
258 if (file)
259 fput(file);
260out:
261 return retval;
262}
263
264asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len,
265 unsigned long prot, unsigned long flags, unsigned long fd,
266 unsigned long pgoff)
267{
268
269
270 return do_mmap2(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT - 12));
271}
272
273asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
274 unsigned long prot, unsigned long flags, unsigned long fd,
275 unsigned long off)
276{
277 return do_mmap2(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
278}
279
280long sparc_remap_file_pages(unsigned long start, unsigned long size,
281 unsigned long prot, unsigned long pgoff,
282 unsigned long flags)
283{
284
285
286
287 return sys_remap_file_pages(start, size, prot,
288 (pgoff >> (PAGE_SHIFT - 12)), flags);
289}
290
291extern unsigned long do_mremap(unsigned long addr,
292 unsigned long old_len, unsigned long new_len,
293 unsigned long flags, unsigned long new_addr);
294
295asmlinkage unsigned long sparc_mremap(unsigned long addr,
296 unsigned long old_len, unsigned long new_len,
297 unsigned long flags, unsigned long new_addr)
298{
299 unsigned long ret = -EINVAL;
300
301 if (unlikely(sparc_mmap_check(addr, old_len)))
302 goto out;
303 if (unlikely(sparc_mmap_check(new_addr, new_len)))
304 goto out;
305 down_write(¤t->mm->mmap_sem);
306 ret = do_mremap(addr, old_len, new_len, flags, new_addr);
307 up_write(¤t->mm->mmap_sem);
308out:
309 return ret;
310}
311
312
313asmlinkage unsigned long
314c_sys_nis_syscall (struct pt_regs *regs)
315{
316 static int count = 0;
317
318 if (count++ > 5)
319 return -ENOSYS;
320 printk ("%s[%d]: Unimplemented SPARC system call %d\n",
321 current->comm, task_pid_nr(current), (int)regs->u_regs[1]);
322#ifdef DEBUG_UNIMP_SYSCALL
323 show_regs (regs);
324#endif
325 return -ENOSYS;
326}
327
328
329
330asmlinkage void
331sparc_breakpoint (struct pt_regs *regs)
332{
333 siginfo_t info;
334
335 lock_kernel();
336#ifdef DEBUG_SPARC_BREAKPOINT
337 printk ("TRAP: Entering kernel PC=%x, nPC=%x\n", regs->pc, regs->npc);
338#endif
339 info.si_signo = SIGTRAP;
340 info.si_errno = 0;
341 info.si_code = TRAP_BRKPT;
342 info.si_addr = (void __user *)regs->pc;
343 info.si_trapno = 0;
344 force_sig_info(SIGTRAP, &info, current);
345
346#ifdef DEBUG_SPARC_BREAKPOINT
347 printk ("TRAP: Returning to space: PC=%x nPC=%x\n", regs->pc, regs->npc);
348#endif
349 unlock_kernel();
350}
351
352asmlinkage int
353sparc_sigaction (int sig, const struct old_sigaction __user *act,
354 struct old_sigaction __user *oact)
355{
356 struct k_sigaction new_ka, old_ka;
357 int ret;
358
359 if (sig < 0) {
360 current->thread.new_signal = 1;
361 sig = -sig;
362 }
363
364 if (act) {
365 unsigned long mask;
366
367 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
368 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
369 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
370 return -EFAULT;
371 __get_user(new_ka.sa.sa_flags, &act->sa_flags);
372 __get_user(mask, &act->sa_mask);
373 siginitset(&new_ka.sa.sa_mask, mask);
374 new_ka.ka_restorer = NULL;
375 }
376
377 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
378
379 if (!ret && oact) {
380
381
382
383
384
385 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
386 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
387 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
388 return -EFAULT;
389 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
390 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
391 }
392
393 return ret;
394}
395
396asmlinkage long
397sys_rt_sigaction(int sig,
398 const struct sigaction __user *act,
399 struct sigaction __user *oact,
400 void __user *restorer,
401 size_t sigsetsize)
402{
403 struct k_sigaction new_ka, old_ka;
404 int ret;
405
406
407 if (sigsetsize != sizeof(sigset_t))
408 return -EINVAL;
409
410
411
412
413 current->thread.new_signal = 1;
414
415 if (act) {
416 new_ka.ka_restorer = restorer;
417 if (copy_from_user(&new_ka.sa, act, sizeof(*act)))
418 return -EFAULT;
419 }
420
421 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
422
423 if (!ret && oact) {
424 if (copy_to_user(oact, &old_ka.sa, sizeof(*oact)))
425 return -EFAULT;
426 }
427
428 return ret;
429}
430
431asmlinkage int sys_getdomainname(char __user *name, int len)
432{
433 int nlen, err;
434
435 if (len < 0)
436 return -EINVAL;
437
438 down_read(&uts_sem);
439
440 nlen = strlen(utsname()->domainname) + 1;
441 err = -EINVAL;
442 if (nlen > len)
443 goto out;
444
445 err = -EFAULT;
446 if (!copy_to_user(name, utsname()->domainname, nlen))
447 err = 0;
448
449out:
450 up_read(&uts_sem);
451 return err;
452}
453
454
455
456
457
458int kernel_execve(const char *filename, char *const argv[], char *const envp[])
459{
460 long __res;
461 register long __g1 __asm__ ("g1") = __NR_execve;
462 register long __o0 __asm__ ("o0") = (long)(filename);
463 register long __o1 __asm__ ("o1") = (long)(argv);
464 register long __o2 __asm__ ("o2") = (long)(envp);
465 asm volatile ("t 0x10\n\t"
466 "bcc 1f\n\t"
467 "mov %%o0, %0\n\t"
468 "sub %%g0, %%o0, %0\n\t"
469 "1:\n\t"
470 : "=r" (__res), "=&r" (__o0)
471 : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1)
472 : "cc");
473 return __res;
474}
475