Commit | Line | Data |
---|---|---|
1da177e4 | 1 | /* |
30286ef6 | 2 | * Implementation of various system calls for Linux/PowerPC |
1da177e4 | 3 | * |
1da177e4 LT |
4 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) |
5 | * | |
6 | * Derived from "arch/i386/kernel/sys_i386.c" | |
7 | * Adapted from the i386 version by Gary Thomas | |
8 | * Modified by Cort Dougan (cort@cs.nmt.edu) | |
9 | * and Paul Mackerras (paulus@cs.anu.edu.au). | |
10 | * | |
11 | * This file contains various random system calls that | |
12 | * have a non-standard calling sequence on the Linux/PPC | |
13 | * platform. | |
14 | * | |
15 | * This program is free software; you can redistribute it and/or | |
16 | * modify it under the terms of the GNU General Public License | |
17 | * as published by the Free Software Foundation; either version | |
18 | * 2 of the License, or (at your option) any later version. | |
19 | * | |
20 | */ | |
21 | ||
22 | #include <linux/errno.h> | |
23 | #include <linux/sched.h> | |
24 | #include <linux/syscalls.h> | |
25 | #include <linux/mm.h> | |
4e950f6f | 26 | #include <linux/fs.h> |
1da177e4 | 27 | #include <linux/smp.h> |
1da177e4 LT |
28 | #include <linux/sem.h> |
29 | #include <linux/msg.h> | |
30 | #include <linux/shm.h> | |
31 | #include <linux/stat.h> | |
32 | #include <linux/mman.h> | |
33 | #include <linux/sys.h> | |
34 | #include <linux/ipc.h> | |
35 | #include <linux/utsname.h> | |
36 | #include <linux/file.h> | |
1da177e4 LT |
37 | #include <linux/personality.h> |
38 | ||
7c0f6ba6 | 39 | #include <linux/uaccess.h> |
a7f31841 | 40 | #include <asm/syscalls.h> |
1da177e4 LT |
41 | #include <asm/time.h> |
42 | #include <asm/unistd.h> | |
0545d543 | 43 | #include <asm/asm-prototypes.h> |
1da177e4 | 44 | |
9c355917 | 45 | static inline long do_mmap2(unsigned long addr, size_t len, |
30286ef6 PM |
46 | unsigned long prot, unsigned long flags, |
47 | unsigned long fd, unsigned long off, int shift) | |
1da177e4 | 48 | { |
9c355917 | 49 | long ret = -EINVAL; |
1da177e4 | 50 | |
9035cf9a | 51 | if (!arch_validate_prot(prot, addr)) |
ef3d3246 DK |
52 | goto out; |
53 | ||
30286ef6 PM |
54 | if (shift) { |
55 | if (off & ((1 << shift) - 1)) | |
56 | goto out; | |
57 | off >>= shift; | |
58 | } | |
30286ef6 | 59 | |
a90f590a | 60 | ret = ksys_mmap_pgoff(addr, len, prot, flags, fd, off); |
1da177e4 LT |
61 | out: |
62 | return ret; | |
63 | } | |
64 | ||
9c355917 BS |
65 | SYSCALL_DEFINE6(mmap2, unsigned long, addr, size_t, len, |
66 | unsigned long, prot, unsigned long, flags, | |
67 | unsigned long, fd, unsigned long, pgoff) | |
30286ef6 PM |
68 | { |
69 | return do_mmap2(addr, len, prot, flags, fd, pgoff, PAGE_SHIFT-12); | |
70 | } | |
71 | ||
9c355917 BS |
72 | SYSCALL_DEFINE6(mmap, unsigned long, addr, size_t, len, |
73 | unsigned long, prot, unsigned long, flags, | |
74 | unsigned long, fd, off_t, offset) | |
30286ef6 PM |
75 | { |
76 | return do_mmap2(addr, len, prot, flags, fd, offset, PAGE_SHIFT); | |
77 | } | |
78 | ||
79 | #ifdef CONFIG_PPC32 | |
80 | /* | |
81 | * Due to some executables calling the wrong select we sometimes | |
82 | * get wrong args. This determines how the args are being passed | |
83 | * (a single ptr to them all args passed) then calls | |
84 | * sys_select() with the appropriate args. -- Cort | |
85 | */ | |
86 | int | |
87 | ppc_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, struct timeval __user *tvp) | |
88 | { | |
89 | if ( (unsigned long)n >= 4096 ) | |
90 | { | |
91 | unsigned long __user *buffer = (unsigned long __user *)n; | |
96d4f267 | 92 | if (!access_ok(buffer, 5*sizeof(unsigned long)) |
30286ef6 PM |
93 | || __get_user(n, buffer) |
94 | || __get_user(inp, ((fd_set __user * __user *)(buffer+1))) | |
95 | || __get_user(outp, ((fd_set __user * __user *)(buffer+2))) | |
96 | || __get_user(exp, ((fd_set __user * __user *)(buffer+3))) | |
97 | || __get_user(tvp, ((struct timeval __user * __user *)(buffer+4)))) | |
98 | return -EFAULT; | |
99 | } | |
100 | return sys_select(n, inp, outp, exp, tvp); | |
101 | } | |
102 | #endif | |
103 | ||
104 | #ifdef CONFIG_PPC64 | |
ce10d979 | 105 | long ppc64_personality(unsigned long personality) |
1da177e4 | 106 | { |
ce10d979 PM |
107 | long ret; |
108 | ||
109 | if (personality(current->personality) == PER_LINUX32 | |
7256a5d2 JK |
110 | && personality(personality) == PER_LINUX) |
111 | personality = (personality & ~PER_MASK) | PER_LINUX32; | |
ce10d979 | 112 | ret = sys_personality(personality); |
7256a5d2 JK |
113 | if (personality(ret) == PER_LINUX32) |
114 | ret = (ret & ~PER_MASK) | PER_LINUX; | |
ce10d979 | 115 | return ret; |
1da177e4 | 116 | } |
30286ef6 PM |
117 | #endif |
118 | ||
77f543cb PM |
119 | long ppc_fadvise64_64(int fd, int advice, u32 offset_high, u32 offset_low, |
120 | u32 len_high, u32 len_low) | |
121 | { | |
9d5b7c95 DB |
122 | return ksys_fadvise64_64(fd, (u64)offset_high << 32 | offset_low, |
123 | (u64)len_high << 32 | len_low, advice); | |
77f543cb | 124 | } |
529d235a ME |
125 | |
126 | long sys_switch_endian(void) | |
127 | { | |
128 | struct thread_info *ti; | |
129 | ||
130 | current->thread.regs->msr ^= MSR_LE; | |
131 | ||
132 | /* | |
133 | * Set TIF_RESTOREALL so that r3 isn't clobbered on return to | |
134 | * userspace. That also has the effect of restoring the non-volatile | |
135 | * GPRs, so we saved them on the way in here. | |
136 | */ | |
137 | ti = current_thread_info(); | |
138 | ti->flags |= _TIF_RESTOREALL; | |
139 | ||
140 | return 0; | |
141 | } |