| 1 | |
| 2 | |
| 3 | * Implementation of various system calls for Linux/PowerPC
|
| 4 | *
|
| 5 | * Copyright (C) 1995-1996 Gary Thomas ([email protected])
|
| 6 | *
|
| 7 | * Derived from "arch/i386/kernel/sys_i386.c"
|
| 8 | * Adapted from the i386 version by Gary Thomas
|
| 9 | * Modified by Cort Dougan ([email protected])
|
| 10 | * and Paul Mackerras ([email protected]).
|
| 11 | *
|
| 12 | * This file contains various random system calls that
|
| 13 | * have a non-standard calling sequence on the Linux/PPC
|
| 14 | * platform.
|
| 15 |
|
| 16 |
|
| 17 | #include <linux/errno.h>
|
| 18 | #include <linux/sched.h>
|
| 19 | #include <linux/syscalls.h>
|
| 20 | #include <linux/mm.h>
|
| 21 | #include <linux/fs.h>
|
| 22 | #include <linux/smp.h>
|
| 23 | #include <linux/sem.h>
|
| 24 | #include <linux/msg.h>
|
| 25 | #include <linux/shm.h>
|
| 26 | #include <linux/stat.h>
|
| 27 | #include <linux/mman.h>
|
| 28 | #include <linux/sys.h>
|
| 29 | #include <linux/ipc.h>
|
| 30 | #include <linux/utsname.h>
|
| 31 | #include <linux/file.h>
|
| 32 | #include <linux/personality.h>
|
| 33 |
|
| 34 | #include <linux/uaccess.h>
|
| 35 | #include <asm/syscalls.h>
|
| 36 | #include <asm/time.h>
|
| 37 | #include <asm/unistd.h>
|
| 38 |
|
| 39 | static long do_mmap2(unsigned long addr, size_t len,
|
| 40 | unsigned long prot, unsigned long flags,
|
| 41 | unsigned long fd, unsigned long off, int shift)
|
| 42 | {
|
| 43 | if (!arch_validate_prot(prot, addr))
|
| 44 | return -EINVAL;
|
| 45 |
|
| 46 | if (!IS_ALIGNED(off, 1 << shift))
|
| 47 | return -EINVAL;
|
| 48 |
|
| 49 | return ksys_mmap_pgoff(addr, len, prot, flags, fd, off >> shift);
|
| 50 | }
|
| 51 |
|
| 52 | SYSCALL_DEFINE6(mmap2, unsigned long, addr, size_t, len,
|
| 53 | unsigned long, prot, unsigned long, flags,
|
| 54 | unsigned long, fd, unsigned long, pgoff)
|
| 55 | {
|
| 56 | return do_mmap2(addr, len, prot, flags, fd, pgoff, PAGE_SHIFT-12);
|
| 57 | }
|
| 58 |
|
| 59 | #ifdef CONFIG_COMPAT
|
| 60 | COMPAT_SYSCALL_DEFINE6(mmap2,
|
| 61 | unsigned long, addr, size_t, len,
|
| 62 | unsigned long, prot, unsigned long, flags,
|
| 63 | unsigned long, fd, unsigned long, off_4k)
|
| 64 | {
|
| 65 | return do_mmap2(addr, len, prot, flags, fd, off_4k, PAGE_SHIFT-12);
|
| 66 | }
|
| 67 | #endif
|
| 68 |
|
| 69 | SYSCALL_DEFINE6(mmap, unsigned long, addr, size_t, len,
|
| 70 | unsigned long, prot, unsigned long, flags,
|
| 71 | unsigned long, fd, off_t, offset)
|
| 72 | {
|
| 73 | return do_mmap2(addr, len, prot, flags, fd, offset, PAGE_SHIFT);
|
| 74 | }
|
| 75 |
|
| 76 | #ifdef CONFIG_PPC64
|
| 77 | static long do_ppc64_personality(unsigned long personality)
|
| 78 | {
|
| 79 | long ret;
|
| 80 |
|
| 81 | if (personality(current->personality) == PER_LINUX32
|
| 82 | && personality(personality) == PER_LINUX)
|
| 83 | personality = (personality & ~PER_MASK) | PER_LINUX32;
|
| 84 | ret = ksys_personality(personality);
|
| 85 | if (personality(ret) == PER_LINUX32)
|
| 86 | ret = (ret & ~PER_MASK) | PER_LINUX;
|
| 87 | return ret;
|
| 88 | }
|
| 89 |
|
| 90 | SYSCALL_DEFINE1(ppc64_personality, unsigned long, personality)
|
| 91 | {
|
| 92 | return do_ppc64_personality(personality);
|
| 93 | }
|
| 94 |
|
| 95 | #ifdef CONFIG_COMPAT
|
| 96 | COMPAT_SYSCALL_DEFINE1(ppc64_personality, unsigned long, personality)
|
| 97 | {
|
| 98 | return do_ppc64_personality(personality);
|
| 99 | }
|
| 100 | #endif
|
| 101 | #endif
|
| 102 |
|
| 103 | SYSCALL_DEFINE6(ppc_fadvise64_64,
|
| 104 | int, fd, int, advice, u32, offset_high, u32, offset_low,
|
| 105 | u32, len_high, u32, len_low)
|
| 106 | {
|
| 107 | return ksys_fadvise64_64(fd, merge_64(offset_high, offset_low),
|
| 108 | merge_64(len_high, len_low), advice);
|
| 109 | }
|
| 110 |
|
| 111 | SYSCALL_DEFINE0(switch_endian)
|
| 112 | {
|
| 113 | struct thread_info *ti;
|
| 114 |
|
| 115 | regs_set_return_msr(current->thread.regs,
|
| 116 | current->thread.regs->msr ^ MSR_LE);
|
| 117 |
|
| 118 | |
| 119 | * Set TIF_RESTOREALL so that r3 isn't clobbered on return to
|
| 120 | * userspace. That also has the effect of restoring the non-volatile
|
| 121 | * GPRs, so we saved them on the way in here.
|
| 122 |
|
| 123 | ti = current_thread_info();
|
| 124 | ti->flags |= _TIF_RESTOREALL;
|
| 125 |
|
| 126 | return 0;
|
| 127 | }
|