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/] [mips/] [kernel/] [linux32.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
 * Conversion between 32-bit and 64-bit native system calls.
3
 *
4
 * Copyright (C) 2000 Silicon Graphics, Inc.
5
 * Written by Ulf Carlsson (ulfc@engr.sgi.com)
6
 * sys32_execve from ia64/ia32 code, Feb 2000, Kanoj Sarcar (kanoj@sgi.com)
7
 */
8
#include <linux/compiler.h>
9
#include <linux/mm.h>
10
#include <linux/errno.h>
11
#include <linux/file.h>
12
#include <linux/smp_lock.h>
13
#include <linux/highuid.h>
14
#include <linux/dirent.h>
15
#include <linux/resource.h>
16
#include <linux/highmem.h>
17
#include <linux/time.h>
18
#include <linux/times.h>
19
#include <linux/poll.h>
20
#include <linux/slab.h>
21
#include <linux/skbuff.h>
22
#include <linux/filter.h>
23
#include <linux/shm.h>
24
#include <linux/sem.h>
25
#include <linux/msg.h>
26
#include <linux/icmpv6.h>
27
#include <linux/syscalls.h>
28
#include <linux/sysctl.h>
29
#include <linux/utime.h>
30
#include <linux/utsname.h>
31
#include <linux/personality.h>
32
#include <linux/dnotify.h>
33
#include <linux/module.h>
34
#include <linux/binfmts.h>
35
#include <linux/security.h>
36
#include <linux/compat.h>
37
#include <linux/vfs.h>
38
#include <linux/ipc.h>
39
 
40
#include <net/sock.h>
41
#include <net/scm.h>
42
 
43
#include <asm/compat-signal.h>
44
#include <asm/sim.h>
45
#include <asm/uaccess.h>
46
#include <asm/mmu_context.h>
47
#include <asm/mman.h>
48
 
49
/* Use this to get at 32-bit user passed pointers. */
50
/* A() macro should be used for places where you e.g.
51
   have some internal variable u32 and just want to get
52
   rid of a compiler warning. AA() has to be used in
53
   places where you want to convert a function argument
54
   to 32bit pointer or when you e.g. access pt_regs
55
   structure and want to consider 32bit registers only.
56
 */
57
#define A(__x) ((unsigned long)(__x))
58
#define AA(__x) ((unsigned long)((int)__x))
59
 
60
#ifdef __MIPSEB__
61
#define merge_64(r1, r2) ((((r1) & 0xffffffffUL) << 32) + ((r2) & 0xffffffffUL))
62
#endif
63
#ifdef __MIPSEL__
64
#define merge_64(r1, r2) ((((r2) & 0xffffffffUL) << 32) + ((r1) & 0xffffffffUL))
65
#endif
66
 
67
/*
68
 * Revalidate the inode. This is required for proper NFS attribute caching.
69
 */
70
 
71
int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
72
{
73
        struct compat_stat tmp;
74
 
75
        if (!new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev))
76
                return -EOVERFLOW;
77
 
78
        memset(&tmp, 0, sizeof(tmp));
79
        tmp.st_dev = new_encode_dev(stat->dev);
80
        tmp.st_ino = stat->ino;
81
        if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
82
                return -EOVERFLOW;
83
        tmp.st_mode = stat->mode;
84
        tmp.st_nlink = stat->nlink;
85
        SET_UID(tmp.st_uid, stat->uid);
86
        SET_GID(tmp.st_gid, stat->gid);
87
        tmp.st_rdev = new_encode_dev(stat->rdev);
88
        tmp.st_size = stat->size;
89
        tmp.st_atime = stat->atime.tv_sec;
90
        tmp.st_mtime = stat->mtime.tv_sec;
91
        tmp.st_ctime = stat->ctime.tv_sec;
92
#ifdef STAT_HAVE_NSEC
93
        tmp.st_atime_nsec = stat->atime.tv_nsec;
94
        tmp.st_mtime_nsec = stat->mtime.tv_nsec;
95
        tmp.st_ctime_nsec = stat->ctime.tv_nsec;
96
#endif
97
        tmp.st_blocks = stat->blocks;
98
        tmp.st_blksize = stat->blksize;
99
        return copy_to_user(statbuf, &tmp, sizeof(tmp)) ? -EFAULT : 0;
100
}
101
 
102
asmlinkage unsigned long
103
sys32_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
104
         unsigned long flags, unsigned long fd, unsigned long pgoff)
105
{
106
        struct file * file = NULL;
107
        unsigned long error;
108
 
109
        error = -EINVAL;
110
        if (pgoff & (~PAGE_MASK >> 12))
111
                goto out;
112
        pgoff >>= PAGE_SHIFT-12;
113
 
114
        if (!(flags & MAP_ANONYMOUS)) {
115
                error = -EBADF;
116
                file = fget(fd);
117
                if (!file)
118
                        goto out;
119
        }
120
        flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
121
 
122
        down_write(&current->mm->mmap_sem);
123
        error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
124
        up_write(&current->mm->mmap_sem);
125
        if (file)
126
                fput(file);
127
 
128
out:
129
        return error;
130
}
131
 
132
 
133
asmlinkage int sys_truncate64(const char __user *path, unsigned int high,
134
                              unsigned int low)
135
{
136
        if ((int)high < 0)
137
                return -EINVAL;
138
        return sys_truncate(path, ((long) high << 32) | low);
139
}
140
 
141
asmlinkage int sys_ftruncate64(unsigned int fd, unsigned int high,
142
                               unsigned int low)
143
{
144
        if ((int)high < 0)
145
                return -EINVAL;
146
        return sys_ftruncate(fd, ((long) high << 32) | low);
147
}
148
 
149
/*
150
 * sys_execve() executes a new program.
151
 */
152
asmlinkage int sys32_execve(nabi_no_regargs struct pt_regs regs)
153
{
154
        int error;
155
        char * filename;
156
 
157
        filename = getname(compat_ptr(regs.regs[4]));
158
        error = PTR_ERR(filename);
159
        if (IS_ERR(filename))
160
                goto out;
161
        error = compat_do_execve(filename, compat_ptr(regs.regs[5]),
162
                                 compat_ptr(regs.regs[6]), &regs);
163
        putname(filename);
164
 
165
out:
166
        return error;
167
}
168
 
169
#define RLIM_INFINITY32 0x7fffffff
170
#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
171
 
172
struct rlimit32 {
173
        int     rlim_cur;
174
        int     rlim_max;
175
};
176
 
177
#ifdef __MIPSEB__
178
asmlinkage long sys32_truncate64(const char __user * path, unsigned long __dummy,
179
        int length_hi, int length_lo)
180
#endif
181
#ifdef __MIPSEL__
182
asmlinkage long sys32_truncate64(const char __user * path, unsigned long __dummy,
183
        int length_lo, int length_hi)
184
#endif
185
{
186
        loff_t length;
187
 
188
        length = ((unsigned long) length_hi << 32) | (unsigned int) length_lo;
189
 
190
        return sys_truncate(path, length);
191
}
192
 
193
#ifdef __MIPSEB__
194
asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long __dummy,
195
        int length_hi, int length_lo)
196
#endif
197
#ifdef __MIPSEL__
198
asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long __dummy,
199
        int length_lo, int length_hi)
200
#endif
201
{
202
        loff_t length;
203
 
204
        length = ((unsigned long) length_hi << 32) | (unsigned int) length_lo;
205
 
206
        return sys_ftruncate(fd, length);
207
}
208
 
209
static inline long
210
get_tv32(struct timeval *o, struct compat_timeval __user *i)
211
{
212
        return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
213
                (__get_user(o->tv_sec, &i->tv_sec) |
214
                 __get_user(o->tv_usec, &i->tv_usec)));
215
}
216
 
217
static inline long
218
put_tv32(struct compat_timeval __user *o, struct timeval *i)
219
{
220
        return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
221
                (__put_user(i->tv_sec, &o->tv_sec) |
222
                 __put_user(i->tv_usec, &o->tv_usec)));
223
}
224
 
225
extern struct timezone sys_tz;
226
 
227
asmlinkage int
228
sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
229
{
230
        if (tv) {
231
                struct timeval ktv;
232
                do_gettimeofday(&ktv);
233
                if (put_tv32(tv, &ktv))
234
                        return -EFAULT;
235
        }
236
        if (tz) {
237
                if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
238
                        return -EFAULT;
239
        }
240
        return 0;
241
}
242
 
243
static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
244
{
245
        long usec;
246
 
247
        if (!access_ok(VERIFY_READ, i, sizeof(*i)))
248
                return -EFAULT;
249
        if (__get_user(o->tv_sec, &i->tv_sec))
250
                return -EFAULT;
251
        if (__get_user(usec, &i->tv_usec))
252
                return -EFAULT;
253
        o->tv_nsec = usec * 1000;
254
                return 0;
255
}
256
 
257
asmlinkage int
258
sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
259
{
260
        struct timespec kts;
261
        struct timezone ktz;
262
 
263
        if (tv) {
264
                if (get_ts32(&kts, tv))
265
                        return -EFAULT;
266
        }
267
        if (tz) {
268
                if (copy_from_user(&ktz, tz, sizeof(ktz)))
269
                        return -EFAULT;
270
        }
271
 
272
        return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
273
}
274
 
275
asmlinkage int sys32_llseek(unsigned int fd, unsigned int offset_high,
276
                            unsigned int offset_low, loff_t __user * result,
277
                            unsigned int origin)
278
{
279
        return sys_llseek(fd, offset_high, offset_low, result, origin);
280
}
281
 
282
/* From the Single Unix Spec: pread & pwrite act like lseek to pos + op +
283
   lseek back to original location.  They fail just like lseek does on
284
   non-seekable files.  */
285
 
286
asmlinkage ssize_t sys32_pread(unsigned int fd, char __user * buf,
287
                               size_t count, u32 unused, u64 a4, u64 a5)
288
{
289
        return sys_pread64(fd, buf, count, merge_64(a4, a5));
290
}
291
 
292
asmlinkage ssize_t sys32_pwrite(unsigned int fd, const char __user * buf,
293
                                size_t count, u32 unused, u64 a4, u64 a5)
294
{
295
        return sys_pwrite64(fd, buf, count, merge_64(a4, a5));
296
}
297
 
298
asmlinkage int sys32_sched_rr_get_interval(compat_pid_t pid,
299
        struct compat_timespec __user *interval)
300
{
301
        struct timespec t;
302
        int ret;
303
        mm_segment_t old_fs = get_fs();
304
 
305
        set_fs(KERNEL_DS);
306
        ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t);
307
        set_fs(old_fs);
308
        if (put_user (t.tv_sec, &interval->tv_sec) ||
309
            __put_user(t.tv_nsec, &interval->tv_nsec))
310
                return -EFAULT;
311
        return ret;
312
}
313
 
314
#ifdef CONFIG_SYSVIPC
315
 
316
asmlinkage long
317
sys32_ipc(u32 call, int first, int second, int third, u32 ptr, u32 fifth)
318
{
319
        int version, err;
320
 
321
        version = call >> 16; /* hack for backward compatibility */
322
        call &= 0xffff;
323
 
324
        switch (call) {
325
        case SEMOP:
326
                /* struct sembuf is the same on 32 and 64bit :)) */
327
                err = sys_semtimedop(first, compat_ptr(ptr), second, NULL);
328
                break;
329
        case SEMTIMEDOP:
330
                err = compat_sys_semtimedop(first, compat_ptr(ptr), second,
331
                                            compat_ptr(fifth));
332
                break;
333
        case SEMGET:
334
                err = sys_semget(first, second, third);
335
                break;
336
        case SEMCTL:
337
                err = compat_sys_semctl(first, second, third, compat_ptr(ptr));
338
                break;
339
        case MSGSND:
340
                err = compat_sys_msgsnd(first, second, third, compat_ptr(ptr));
341
                break;
342
        case MSGRCV:
343
                err = compat_sys_msgrcv(first, second, fifth, third,
344
                                        version, compat_ptr(ptr));
345
                break;
346
        case MSGGET:
347
                err = sys_msgget((key_t) first, second);
348
                break;
349
        case MSGCTL:
350
                err = compat_sys_msgctl(first, second, compat_ptr(ptr));
351
                break;
352
        case SHMAT:
353
                err = compat_sys_shmat(first, second, third, version,
354
                                       compat_ptr(ptr));
355
                break;
356
        case SHMDT:
357
                err = sys_shmdt(compat_ptr(ptr));
358
                break;
359
        case SHMGET:
360
                err = sys_shmget(first, (unsigned)second, third);
361
                break;
362
        case SHMCTL:
363
                err = compat_sys_shmctl(first, second, compat_ptr(ptr));
364
                break;
365
        default:
366
                err = -EINVAL;
367
                break;
368
        }
369
 
370
        return err;
371
}
372
 
373
#else
374
 
375
asmlinkage long
376
sys32_ipc(u32 call, int first, int second, int third, u32 ptr, u32 fifth)
377
{
378
        return -ENOSYS;
379
}
380
 
381
#endif /* CONFIG_SYSVIPC */
382
 
383
#ifdef CONFIG_MIPS32_N32
384
asmlinkage long sysn32_semctl(int semid, int semnum, int cmd, u32 arg)
385
{
386
        /* compat_sys_semctl expects a pointer to union semun */
387
        u32 __user *uptr = compat_alloc_user_space(sizeof(u32));
388
        if (put_user(arg, uptr))
389
                return -EFAULT;
390
        return compat_sys_semctl(semid, semnum, cmd, uptr);
391
}
392
 
393
asmlinkage long sysn32_msgsnd(int msqid, u32 msgp, unsigned msgsz, int msgflg)
394
{
395
        return compat_sys_msgsnd(msqid, msgsz, msgflg, compat_ptr(msgp));
396
}
397
 
398
asmlinkage long sysn32_msgrcv(int msqid, u32 msgp, size_t msgsz, int msgtyp,
399
                              int msgflg)
400
{
401
        return compat_sys_msgrcv(msqid, msgsz, msgtyp, msgflg, IPC_64,
402
                                 compat_ptr(msgp));
403
}
404
#endif
405
 
406
struct sysctl_args32
407
{
408
        compat_caddr_t name;
409
        int nlen;
410
        compat_caddr_t oldval;
411
        compat_caddr_t oldlenp;
412
        compat_caddr_t newval;
413
        compat_size_t newlen;
414
        unsigned int __unused[4];
415
};
416
 
417
#ifdef CONFIG_SYSCTL_SYSCALL
418
 
419
asmlinkage long sys32_sysctl(struct sysctl_args32 __user *args)
420
{
421
        struct sysctl_args32 tmp;
422
        int error;
423
        size_t oldlen;
424
        size_t __user *oldlenp = NULL;
425
        unsigned long addr = (((unsigned long)&args->__unused[0]) + 7) & ~7;
426
 
427
        if (copy_from_user(&tmp, args, sizeof(tmp)))
428
                return -EFAULT;
429
 
430
        if (tmp.oldval && tmp.oldlenp) {
431
                /* Duh, this is ugly and might not work if sysctl_args
432
                   is in read-only memory, but do_sysctl does indirectly
433
                   a lot of uaccess in both directions and we'd have to
434
                   basically copy the whole sysctl.c here, and
435
                   glibc's __sysctl uses rw memory for the structure
436
                   anyway.  */
437
                if (get_user(oldlen, (u32 __user *)A(tmp.oldlenp)) ||
438
                    put_user(oldlen, (size_t __user *)addr))
439
                        return -EFAULT;
440
                oldlenp = (size_t __user *)addr;
441
        }
442
 
443
        lock_kernel();
444
        error = do_sysctl((int __user *)A(tmp.name), tmp.nlen, (void __user *)A(tmp.oldval),
445
                          oldlenp, (void __user *)A(tmp.newval), tmp.newlen);
446
        unlock_kernel();
447
        if (oldlenp) {
448
                if (!error) {
449
                        if (get_user(oldlen, (size_t __user *)addr) ||
450
                            put_user(oldlen, (u32 __user *)A(tmp.oldlenp)))
451
                                error = -EFAULT;
452
                }
453
                copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
454
        }
455
        return error;
456
}
457
 
458
#endif /* CONFIG_SYSCTL_SYSCALL */
459
 
460
asmlinkage long sys32_newuname(struct new_utsname __user * name)
461
{
462
        int ret = 0;
463
 
464
        down_read(&uts_sem);
465
        if (copy_to_user(name, utsname(), sizeof *name))
466
                ret = -EFAULT;
467
        up_read(&uts_sem);
468
 
469
        if (current->personality == PER_LINUX32 && !ret)
470
                if (copy_to_user(name->machine, "mips\0\0\0", 8))
471
                        ret = -EFAULT;
472
 
473
        return ret;
474
}
475
 
476
asmlinkage int sys32_personality(unsigned long personality)
477
{
478
        int ret;
479
        personality &= 0xffffffff;
480
        if (personality(current->personality) == PER_LINUX32 &&
481
            personality == PER_LINUX)
482
                personality = PER_LINUX32;
483
        ret = sys_personality(personality);
484
        if (ret == PER_LINUX32)
485
                ret = PER_LINUX;
486
        return ret;
487
}
488
 
489
/* ustat compatibility */
490
struct ustat32 {
491
        compat_daddr_t  f_tfree;
492
        compat_ino_t    f_tinode;
493
        char            f_fname[6];
494
        char            f_fpack[6];
495
};
496
 
497
extern asmlinkage long sys_ustat(dev_t dev, struct ustat __user * ubuf);
498
 
499
asmlinkage int sys32_ustat(dev_t dev, struct ustat32 __user * ubuf32)
500
{
501
        int err;
502
        struct ustat tmp;
503
        struct ustat32 tmp32;
504
        mm_segment_t old_fs = get_fs();
505
 
506
        set_fs(KERNEL_DS);
507
        err = sys_ustat(dev, (struct ustat __user *)&tmp);
508
        set_fs(old_fs);
509
 
510
        if (err)
511
                goto out;
512
 
513
        memset(&tmp32, 0, sizeof(struct ustat32));
514
        tmp32.f_tfree = tmp.f_tfree;
515
        tmp32.f_tinode = tmp.f_tinode;
516
 
517
        err = copy_to_user(ubuf32, &tmp32, sizeof(struct ustat32)) ? -EFAULT : 0;
518
 
519
out:
520
        return err;
521
}
522
 
523
asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset,
524
        s32 count)
525
{
526
        mm_segment_t old_fs = get_fs();
527
        int ret;
528
        off_t of;
529
 
530
        if (offset && get_user(of, offset))
531
                return -EFAULT;
532
 
533
        set_fs(KERNEL_DS);
534
        ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL, count);
535
        set_fs(old_fs);
536
 
537
        if (offset && put_user(of, offset))
538
                return -EFAULT;
539
 
540
        return ret;
541
}
542
 
543
asmlinkage ssize_t sys32_readahead(int fd, u32 pad0, u64 a2, u64 a3,
544
                                   size_t count)
545
{
546
        return sys_readahead(fd, merge_64(a2, a3), count);
547
}
548
 
549
asmlinkage long sys32_sync_file_range(int fd, int __pad,
550
        unsigned long a2, unsigned long a3,
551
        unsigned long a4, unsigned long a5,
552
        int flags)
553
{
554
        return sys_sync_file_range(fd,
555
                        merge_64(a2, a3), merge_64(a4, a5),
556
                        flags);
557
}
558
 
559
asmlinkage long sys32_fadvise64_64(int fd, int __pad,
560
        unsigned long a2, unsigned long a3,
561
        unsigned long a4, unsigned long a5,
562
        int flags)
563
{
564
        return sys_fadvise64_64(fd,
565
                        merge_64(a2, a3), merge_64(a4, a5),
566
                        flags);
567
}
568
 
569
asmlinkage long sys32_fallocate(int fd, int mode, unsigned offset_a2,
570
        unsigned offset_a3, unsigned len_a4, unsigned len_a5)
571
{
572
        return sys_fallocate(fd, mode, merge_64(offset_a2, offset_a3),
573
                             merge_64(len_a4, len_a5));
574
}
575
 
576
save_static_function(sys32_clone);
577
static int noinline __used
578
_sys32_clone(nabi_no_regargs struct pt_regs regs)
579
{
580
        unsigned long clone_flags;
581
        unsigned long newsp;
582
        int __user *parent_tidptr, *child_tidptr;
583
 
584
        clone_flags = regs.regs[4];
585
        newsp = regs.regs[5];
586
        if (!newsp)
587
                newsp = regs.regs[29];
588
        parent_tidptr = (int __user *) regs.regs[6];
589
 
590
        /* Use __dummy4 instead of getting it off the stack, so that
591
           syscall() works.  */
592
        child_tidptr = (int __user *) __dummy4;
593
        return do_fork(clone_flags, newsp, &regs, 0,
594
                       parent_tidptr, child_tidptr);
595
}

powered by: WebSVN 2.1.0

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