OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [arch/] [sparc/] [kernel/] [sys_sparc.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/* $Id: sys_sparc.c,v 1.70 2001/04/14 01:12:02 davem Exp $
2
 * linux/arch/sparc/kernel/sys_sparc.c
3
 *
4
 * This file contains various random system calls that
5
 * have a non-standard calling sequence on the Linux/sparc
6
 * platform.
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
/* #define DEBUG_UNIMP_SYSCALL */
30
 
31
/* XXX Make this per-binary type, this way we can detect the type of
32
 * XXX a binary.  Every Sparc executable calls this very early on.
33
 */
34
asmlinkage unsigned long sys_getpagesize(void)
35
{
36
        return PAGE_SIZE; /* Possibly older binaries want 8192 on sun4's? */
37
}
38
 
39
#define COLOUR_ALIGN(addr)      (((addr)+SHMLBA-1)&~(SHMLBA-1))
40
 
41
unsigned 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
                /* We do not accept a shared mapping if it would violate
47
                 * cache aliasing constraints.
48
                 */
49
                if ((flags & MAP_SHARED) && (addr & (SHMLBA - 1)))
50
                        return -EINVAL;
51
                return addr;
52
        }
53
 
54
        /* See asm-sparc/uaccess.h */
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
                /* At this point:  (!vmm || addr < vmm->vm_end). */
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
 
83
asmlinkage 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
 * sys_pipe() is the normal C calling standard for creating
94
 * a pipe. It's not the way unix traditionally does this, though.
95
 */
96
asmlinkage 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];
106
out:
107
        return error;
108
}
109
 
110
/*
111
 * sys_ipc() is the de-multiplexer for the SysV IPC calls..
112
 *
113
 * This is really horribly ugly.
114
 */
115
 
116
asmlinkage 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; /* hack for backward compatibility */
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: /* iBCS2 emulator entry point */
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;
219
out:
220
        return err;
221
}
222
 
223
int sparc_mmap_check(unsigned long addr, unsigned long len, unsigned long flags)
224
{
225
        if (ARCH_SUN4C_SUN4 &&
226
            (len > 0x20000000 ||
227
             ((flags & MAP_FIXED) &&
228
              addr < 0xe0000000 && addr + len > 0x20000000)))
229
                return -EINVAL;
230
 
231
        /* See asm-sparc/uaccess.h */
232
        if (len > TASK_SIZE - PAGE_SIZE || addr + len > TASK_SIZE - PAGE_SIZE)
233
                return -EINVAL;
234
 
235
        return 0;
236
}
237
 
238
/* Linux version of mmap */
239
static unsigned long do_mmap2(unsigned long addr, unsigned long len,
240
        unsigned long prot, unsigned long flags, unsigned long fd,
241
        unsigned long pgoff)
242
{
243
        struct file * file = NULL;
244
        unsigned long retval = -EBADF;
245
 
246
        if (!(flags & MAP_ANONYMOUS)) {
247
                file = fget(fd);
248
                if (!file)
249
                        goto out;
250
        }
251
 
252
        len = PAGE_ALIGN(len);
253
        flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
254
 
255
        down_write(&current->mm->mmap_sem);
256
        retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
257
        up_write(&current->mm->mmap_sem);
258
 
259
        if (file)
260
                fput(file);
261
out:
262
        return retval;
263
}
264
 
265
asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len,
266
        unsigned long prot, unsigned long flags, unsigned long fd,
267
        unsigned long pgoff)
268
{
269
        /* Make sure the shift for mmap2 is constant (12), no matter what PAGE_SIZE
270
           we have. */
271
        return do_mmap2(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT - 12));
272
}
273
 
274
asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
275
        unsigned long prot, unsigned long flags, unsigned long fd,
276
        unsigned long off)
277
{
278
        return do_mmap2(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
279
}
280
 
281
long sparc_remap_file_pages(unsigned long start, unsigned long size,
282
                           unsigned long prot, unsigned long pgoff,
283
                           unsigned long flags)
284
{
285
        /* This works on an existing mmap so we don't need to validate
286
         * the range as that was done at the original mmap call.
287
         */
288
        return sys_remap_file_pages(start, size, prot,
289
                                    (pgoff >> (PAGE_SHIFT - 12)), flags);
290
}
291
 
292
extern unsigned long do_mremap(unsigned long addr,
293
        unsigned long old_len, unsigned long new_len,
294
        unsigned long flags, unsigned long new_addr);
295
 
296
asmlinkage unsigned long sparc_mremap(unsigned long addr,
297
        unsigned long old_len, unsigned long new_len,
298
        unsigned long flags, unsigned long new_addr)
299
{
300
        struct vm_area_struct *vma;
301
        unsigned long ret = -EINVAL;
302
        if (ARCH_SUN4C_SUN4) {
303
                if (old_len > 0x20000000 || new_len > 0x20000000)
304
                        goto out;
305
                if (addr < 0xe0000000 && addr + old_len > 0x20000000)
306
                        goto out;
307
        }
308
        if (old_len > TASK_SIZE - PAGE_SIZE ||
309
            new_len > TASK_SIZE - PAGE_SIZE)
310
                goto out;
311
        down_write(&current->mm->mmap_sem);
312
        if (flags & MREMAP_FIXED) {
313
                if (ARCH_SUN4C_SUN4 &&
314
                    new_addr < 0xe0000000 &&
315
                    new_addr + new_len > 0x20000000)
316
                        goto out_sem;
317
                if (new_addr + new_len > TASK_SIZE - PAGE_SIZE)
318
                        goto out_sem;
319
        } else if ((ARCH_SUN4C_SUN4 && addr < 0xe0000000 &&
320
                    addr + new_len > 0x20000000) ||
321
                   addr + new_len > TASK_SIZE - PAGE_SIZE) {
322
                unsigned long map_flags = 0;
323
                struct file *file = NULL;
324
 
325
                ret = -ENOMEM;
326
                if (!(flags & MREMAP_MAYMOVE))
327
                        goto out_sem;
328
 
329
                vma = find_vma(current->mm, addr);
330
                if (vma) {
331
                        if (vma->vm_flags & VM_SHARED)
332
                                map_flags |= MAP_SHARED;
333
                        file = vma->vm_file;
334
                }
335
 
336
                new_addr = get_unmapped_area(file, addr, new_len,
337
                                     vma ? vma->vm_pgoff : 0,
338
                                     map_flags);
339
                ret = new_addr;
340
                if (new_addr & ~PAGE_MASK)
341
                        goto out_sem;
342
                flags |= MREMAP_FIXED;
343
        }
344
        ret = do_mremap(addr, old_len, new_len, flags, new_addr);
345
out_sem:
346
        up_write(&current->mm->mmap_sem);
347
out:
348
        return ret;
349
}
350
 
351
/* we come to here via sys_nis_syscall so it can setup the regs argument */
352
asmlinkage unsigned long
353
c_sys_nis_syscall (struct pt_regs *regs)
354
{
355
        static int count = 0;
356
 
357
        if (count++ > 5)
358
                return -ENOSYS;
359
        printk ("%s[%d]: Unimplemented SPARC system call %d\n",
360
                current->comm, task_pid_nr(current), (int)regs->u_regs[1]);
361
#ifdef DEBUG_UNIMP_SYSCALL      
362
        show_regs (regs);
363
#endif
364
        return -ENOSYS;
365
}
366
 
367
/* #define DEBUG_SPARC_BREAKPOINT */
368
 
369
asmlinkage void
370
sparc_breakpoint (struct pt_regs *regs)
371
{
372
        siginfo_t info;
373
 
374
        lock_kernel();
375
#ifdef DEBUG_SPARC_BREAKPOINT
376
        printk ("TRAP: Entering kernel PC=%x, nPC=%x\n", regs->pc, regs->npc);
377
#endif
378
        info.si_signo = SIGTRAP;
379
        info.si_errno = 0;
380
        info.si_code = TRAP_BRKPT;
381
        info.si_addr = (void __user *)regs->pc;
382
        info.si_trapno = 0;
383
        force_sig_info(SIGTRAP, &info, current);
384
 
385
#ifdef DEBUG_SPARC_BREAKPOINT
386
        printk ("TRAP: Returning to space: PC=%x nPC=%x\n", regs->pc, regs->npc);
387
#endif
388
        unlock_kernel();
389
}
390
 
391
asmlinkage int
392
sparc_sigaction (int sig, const struct old_sigaction __user *act,
393
                 struct old_sigaction __user *oact)
394
{
395
        struct k_sigaction new_ka, old_ka;
396
        int ret;
397
 
398
        if (sig < 0) {
399
                current->thread.new_signal = 1;
400
                sig = -sig;
401
        }
402
 
403
        if (act) {
404
                unsigned long mask;
405
 
406
                if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
407
                    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
408
                    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
409
                        return -EFAULT;
410
                __get_user(new_ka.sa.sa_flags, &act->sa_flags);
411
                __get_user(mask, &act->sa_mask);
412
                siginitset(&new_ka.sa.sa_mask, mask);
413
                new_ka.ka_restorer = NULL;
414
        }
415
 
416
        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
417
 
418
        if (!ret && oact) {
419
                /* In the clone() case we could copy half consistent
420
                 * state to the user, however this could sleep and
421
                 * deadlock us if we held the signal lock on SMP.  So for
422
                 * now I take the easy way out and do no locking.
423
                 */
424
                if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
425
                    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
426
                    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
427
                        return -EFAULT;
428
                __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
429
                __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
430
        }
431
 
432
        return ret;
433
}
434
 
435
asmlinkage long
436
sys_rt_sigaction(int sig,
437
                 const struct sigaction __user *act,
438
                 struct sigaction __user *oact,
439
                 void __user *restorer,
440
                 size_t sigsetsize)
441
{
442
        struct k_sigaction new_ka, old_ka;
443
        int ret;
444
 
445
        /* XXX: Don't preclude handling different sized sigset_t's.  */
446
        if (sigsetsize != sizeof(sigset_t))
447
                return -EINVAL;
448
 
449
        /* All tasks which use RT signals (effectively) use
450
         * new style signals.
451
         */
452
        current->thread.new_signal = 1;
453
 
454
        if (act) {
455
                new_ka.ka_restorer = restorer;
456
                if (copy_from_user(&new_ka.sa, act, sizeof(*act)))
457
                        return -EFAULT;
458
        }
459
 
460
        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
461
 
462
        if (!ret && oact) {
463
                if (copy_to_user(oact, &old_ka.sa, sizeof(*oact)))
464
                        return -EFAULT;
465
        }
466
 
467
        return ret;
468
}
469
 
470
asmlinkage int sys_getdomainname(char __user *name, int len)
471
{
472
        int nlen, err;
473
 
474
        if (len < 0)
475
                return -EINVAL;
476
 
477
        down_read(&uts_sem);
478
 
479
        nlen = strlen(utsname()->domainname) + 1;
480
        err = -EINVAL;
481
        if (nlen > len)
482
                goto out;
483
 
484
        err = -EFAULT;
485
        if (!copy_to_user(name, utsname()->domainname, nlen))
486
                err = 0;
487
 
488
out:
489
        up_read(&uts_sem);
490
        return err;
491
}
492
 
493
/*
494
 * Do a system call from kernel instead of calling sys_execve so we
495
 * end up with proper pt_regs.
496
 */
497
int kernel_execve(const char *filename, char *const argv[], char *const envp[])
498
{
499
        long __res;
500
        register long __g1 __asm__ ("g1") = __NR_execve;
501
        register long __o0 __asm__ ("o0") = (long)(filename);
502
        register long __o1 __asm__ ("o1") = (long)(argv);
503
        register long __o2 __asm__ ("o2") = (long)(envp);
504
        asm volatile ("t 0x10\n\t"
505
                      "bcc 1f\n\t"
506
                      "mov %%o0, %0\n\t"
507
                      "sub %%g0, %%o0, %0\n\t"
508
                      "1:\n\t"
509
                      : "=r" (__res), "=&r" (__o0)
510
                      : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1)
511
                      : "cc");
512
        return __res;
513
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.