This source file includes following definitions.
- sys_pipe
- sys_mmap
- sys_idle
- sys_fork
- sys_clone
- sys_execve
- sys_syscall
- do_sys
1
2
3
4
5
6
7
8
9
10 #include <linux/linkage.h>
11 #include <linux/mm.h>
12 #include <linux/mman.h>
13 #include <linux/sched.h>
14 #include <linux/unistd.h>
15 #include <asm/ptrace.h>
16 #include <asm/segment.h>
17 #include <asm/signal.h>
18
19 extern asmlinkage void syscall_trace(void);
20 typedef asmlinkage int (*syscall_t)(void *a0,...);
21 extern asmlinkage int do_syscalls(struct pt_regs *regs, syscall_t fun,
22 int narg);
23 extern syscall_t sys_call_table[];
24 extern unsigned char sys_narg_table[];
25
26 asmlinkage int sys_pipe(struct pt_regs *regs)
27 {
28 int fd[2];
29 int error;
30
31 error = do_pipe(fd);
32 if (error)
33 return error;
34 regs->reg2 = fd[0];
35 regs->reg3 = fd[1];
36 return 0;
37 }
38
39 asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len, int prot,
40 int flags, int fd, off_t offset)
41 {
42 struct file * file = NULL;
43
44 if (flags & MAP_RENAME) {
45 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
46 return -EBADF;
47 }
48 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
49
50 return do_mmap(file, addr, len, prot, flags, offset);
51 }
52
53 asmlinkage int sys_idle(void)
54 {
55 if (current->pid != 0)
56 return -EPERM;
57
58
59 current->counter = -100;
60 for (;;) {
61
62
63
64 if (wait_available && !need_resched)
65 __asm__(".set\tmips3\n\t"
66 "wait\n\t"
67 ".set\tmips0\n\t");
68 schedule();
69 }
70 }
71
72 asmlinkage int sys_fork(struct pt_regs *regs)
73 {
74 return do_fork(SIGCHLD, regs->reg29, regs);
75 }
76
77 asmlinkage int sys_clone(struct pt_regs *regs)
78 {
79 unsigned long clone_flags;
80 unsigned long newsp;
81
82 clone_flags = regs->reg4;
83 newsp = regs->reg5;
84 if (!newsp)
85 newsp = regs->reg29;
86 return do_fork(clone_flags, newsp, regs);
87 }
88
89
90
91
92 asmlinkage int sys_execve(struct pt_regs *regs)
93 {
94 int error;
95 char * filename;
96
97 error = getname((char *) regs->reg4, &filename);
98 if (error)
99 return error;
100 error = do_execve(filename, (char **) regs->reg5,
101 (char **) regs->reg6, regs);
102 putname(filename);
103 return error;
104 }
105
106
107
108
109 asmlinkage int sys_syscall(unsigned long a0, unsigned long a1, unsigned long a2,
110 unsigned long a3, unsigned long a4, unsigned long a5,
111 unsigned long a6)
112 {
113 syscall_t syscall;
114
115 if (a0 > __NR_Linux + __NR_Linux_syscalls)
116 return -ENOSYS;
117
118 syscall = sys_call_table[a0];
119
120
121
122
123 if (syscall == (syscall_t) sys_syscall)
124 return -EINVAL;
125
126 if (syscall == NULL)
127 return -ENOSYS;
128
129 return syscall((void *)a0, a1, a2, a3, a4, a5, a6);
130 }
131
132 void do_sys(struct pt_regs *regs)
133 {
134 unsigned long syscallnr, usp;
135 syscall_t syscall;
136 int errno, narg;
137
138
139
140
141 if (regs->cp0_cause & CAUSEF_BD)
142 {
143
144
145
146
147
148 printk("%s: syscall in branch delay slot.\n", current->comm);
149 current->sig->action[SIGILL-1].sa_handler = NULL;
150 current->blocked &= ~(1<<(SIGILL-1));
151 send_sig(SIGILL, current, 1);
152 return;
153 }
154 regs->cp0_epc += 4;
155
156 syscallnr = regs->reg2;
157 if (syscallnr > (__NR_Linux + __NR_Linux_syscalls))
158 goto illegal_syscall;
159
160 syscall = sys_call_table[syscallnr];
161 if (syscall == NULL)
162 goto illegal_syscall;
163
164 narg = sys_narg_table[syscallnr];
165 if (narg > 4)
166 {
167
168
169
170
171
172
173 usp = regs->reg29;
174 if (usp & 3)
175 {
176 printk("unaligned usp\n");
177 send_sig(SIGSEGV, current, 1);
178 regs->reg2 = EFAULT;
179 regs->reg7 = 1;
180 return;
181 }
182 errno = verify_area(VERIFY_READ, (void *) (usp + 16),
183 (narg - 4) * sizeof(unsigned long));
184 if (errno < 0)
185 goto bad_syscall;
186 }
187
188 if ((current->flags & PF_TRACESYS) == 0)
189 {
190 errno = do_syscalls(regs, syscall, narg);
191 if (errno < 0 || current->errno)
192 goto bad_syscall;
193
194 regs->reg2 = errno;
195 regs->reg7 = 0;
196 }
197 else
198 {
199 syscall_trace();
200
201 errno = do_syscalls(regs, syscall, narg);
202 if (errno < 0 || current->errno)
203 {
204 regs->reg2 = -errno;
205 regs->reg7 = 1;
206 }
207 else
208 {
209 regs->reg2 = errno;
210 regs->reg7 = 0;
211 }
212
213 syscall_trace();
214 }
215 return;
216
217 bad_syscall:
218 regs->reg2 = -errno;
219 regs->reg7 = 1;
220 return;
221 illegal_syscall:
222 regs->reg2 = ENOSYS;
223 regs->reg7 = 1;
224 return;
225 }