diff options
Diffstat (limited to 'arch/mips/kernel/linux32.c')
-rw-r--r-- | arch/mips/kernel/linux32.c | 164 |
1 files changed, 96 insertions, 68 deletions
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index ece4564919d8..330cf84d21fe 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c | |||
@@ -215,81 +215,32 @@ sys32_readdir(unsigned int fd, void * dirent32, unsigned int count) | |||
215 | return(n); | 215 | return(n); |
216 | } | 216 | } |
217 | 217 | ||
218 | struct rusage32 { | 218 | asmlinkage int |
219 | struct compat_timeval ru_utime; | 219 | sys32_waitpid(compat_pid_t pid, unsigned int *stat_addr, int options) |
220 | struct compat_timeval ru_stime; | ||
221 | int ru_maxrss; | ||
222 | int ru_ixrss; | ||
223 | int ru_idrss; | ||
224 | int ru_isrss; | ||
225 | int ru_minflt; | ||
226 | int ru_majflt; | ||
227 | int ru_nswap; | ||
228 | int ru_inblock; | ||
229 | int ru_oublock; | ||
230 | int ru_msgsnd; | ||
231 | int ru_msgrcv; | ||
232 | int ru_nsignals; | ||
233 | int ru_nvcsw; | ||
234 | int ru_nivcsw; | ||
235 | }; | ||
236 | |||
237 | static int | ||
238 | put_rusage (struct rusage32 *ru, struct rusage *r) | ||
239 | { | 220 | { |
240 | int err; | 221 | return compat_sys_wait4(pid, stat_addr, options, NULL); |
241 | |||
242 | if (!access_ok(VERIFY_WRITE, ru, sizeof *ru)) | ||
243 | return -EFAULT; | ||
244 | |||
245 | err = __put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec); | ||
246 | err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec); | ||
247 | err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec); | ||
248 | err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec); | ||
249 | err |= __put_user (r->ru_maxrss, &ru->ru_maxrss); | ||
250 | err |= __put_user (r->ru_ixrss, &ru->ru_ixrss); | ||
251 | err |= __put_user (r->ru_idrss, &ru->ru_idrss); | ||
252 | err |= __put_user (r->ru_isrss, &ru->ru_isrss); | ||
253 | err |= __put_user (r->ru_minflt, &ru->ru_minflt); | ||
254 | err |= __put_user (r->ru_majflt, &ru->ru_majflt); | ||
255 | err |= __put_user (r->ru_nswap, &ru->ru_nswap); | ||
256 | err |= __put_user (r->ru_inblock, &ru->ru_inblock); | ||
257 | err |= __put_user (r->ru_oublock, &ru->ru_oublock); | ||
258 | err |= __put_user (r->ru_msgsnd, &ru->ru_msgsnd); | ||
259 | err |= __put_user (r->ru_msgrcv, &ru->ru_msgrcv); | ||
260 | err |= __put_user (r->ru_nsignals, &ru->ru_nsignals); | ||
261 | err |= __put_user (r->ru_nvcsw, &ru->ru_nvcsw); | ||
262 | err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw); | ||
263 | |||
264 | return err; | ||
265 | } | 222 | } |
266 | 223 | ||
267 | asmlinkage int | 224 | asmlinkage long |
268 | sys32_wait4(compat_pid_t pid, unsigned int * stat_addr, int options, | 225 | sysn32_waitid(int which, compat_pid_t pid, |
269 | struct rusage32 * ru) | 226 | siginfo_t __user *uinfo, int options, |
227 | struct compat_rusage __user *uru) | ||
270 | { | 228 | { |
271 | if (!ru) | 229 | struct rusage ru; |
272 | return sys_wait4(pid, stat_addr, options, NULL); | 230 | long ret; |
273 | else { | 231 | mm_segment_t old_fs = get_fs(); |
274 | struct rusage r; | ||
275 | int ret; | ||
276 | unsigned int status; | ||
277 | mm_segment_t old_fs = get_fs(); | ||
278 | 232 | ||
279 | set_fs(KERNEL_DS); | 233 | set_fs (KERNEL_DS); |
280 | ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r); | 234 | ret = sys_waitid(which, pid, uinfo, options, |
281 | set_fs(old_fs); | 235 | uru ? (struct rusage __user *) &ru : NULL); |
282 | if (put_rusage (ru, &r)) return -EFAULT; | 236 | set_fs (old_fs); |
283 | if (stat_addr && put_user (status, stat_addr)) | 237 | |
284 | return -EFAULT; | 238 | if (ret < 0 || uinfo->si_signo == 0) |
285 | return ret; | 239 | return ret; |
286 | } | ||
287 | } | ||
288 | 240 | ||
289 | asmlinkage int | 241 | if (uru) |
290 | sys32_waitpid(compat_pid_t pid, unsigned int *stat_addr, int options) | 242 | ret = put_compat_rusage(&ru, uru); |
291 | { | 243 | return ret; |
292 | return sys32_wait4(pid, stat_addr, options, NULL); | ||
293 | } | 244 | } |
294 | 245 | ||
295 | struct sysinfo32 { | 246 | struct sysinfo32 { |
@@ -1467,3 +1418,80 @@ asmlinkage long sys32_socketcall(int call, unsigned int *args32) | |||
1467 | } | 1418 | } |
1468 | return err; | 1419 | return err; |
1469 | } | 1420 | } |
1421 | |||
1422 | struct sigevent32 { | ||
1423 | u32 sigev_value; | ||
1424 | u32 sigev_signo; | ||
1425 | u32 sigev_notify; | ||
1426 | u32 payload[(64 / 4) - 3]; | ||
1427 | }; | ||
1428 | |||
1429 | extern asmlinkage long | ||
1430 | sys_timer_create(clockid_t which_clock, | ||
1431 | struct sigevent __user *timer_event_spec, | ||
1432 | timer_t __user * created_timer_id); | ||
1433 | |||
1434 | long | ||
1435 | sys32_timer_create(u32 clock, struct sigevent32 __user *se32, timer_t __user *timer_id) | ||
1436 | { | ||
1437 | struct sigevent __user *p = NULL; | ||
1438 | if (se32) { | ||
1439 | struct sigevent se; | ||
1440 | p = compat_alloc_user_space(sizeof(struct sigevent)); | ||
1441 | memset(&se, 0, sizeof(struct sigevent)); | ||
1442 | if (get_user(se.sigev_value.sival_int, &se32->sigev_value) || | ||
1443 | __get_user(se.sigev_signo, &se32->sigev_signo) || | ||
1444 | __get_user(se.sigev_notify, &se32->sigev_notify) || | ||
1445 | __copy_from_user(&se._sigev_un._pad, &se32->payload, | ||
1446 | sizeof(se32->payload)) || | ||
1447 | copy_to_user(p, &se, sizeof(se))) | ||
1448 | return -EFAULT; | ||
1449 | } | ||
1450 | return sys_timer_create(clock, p, timer_id); | ||
1451 | } | ||
1452 | |||
1453 | asmlinkage long | ||
1454 | sysn32_rt_sigtimedwait(const sigset_t __user *uthese, | ||
1455 | siginfo_t __user *uinfo, | ||
1456 | const struct compat_timespec __user *uts32, | ||
1457 | size_t sigsetsize) | ||
1458 | { | ||
1459 | struct timespec __user *uts = NULL; | ||
1460 | |||
1461 | if (uts32) { | ||
1462 | struct timespec ts; | ||
1463 | uts = compat_alloc_user_space(sizeof(struct timespec)); | ||
1464 | if (get_user(ts.tv_sec, &uts32->tv_sec) || | ||
1465 | get_user(ts.tv_nsec, &uts32->tv_nsec) || | ||
1466 | copy_to_user (uts, &ts, sizeof (ts))) | ||
1467 | return -EFAULT; | ||
1468 | } | ||
1469 | return sys_rt_sigtimedwait(uthese, uinfo, uts, sigsetsize); | ||
1470 | } | ||
1471 | |||
1472 | save_static_function(sys32_clone); | ||
1473 | __attribute_used__ noinline static int | ||
1474 | _sys32_clone(nabi_no_regargs struct pt_regs regs) | ||
1475 | { | ||
1476 | unsigned long clone_flags; | ||
1477 | unsigned long newsp; | ||
1478 | int __user *parent_tidptr, *child_tidptr; | ||
1479 | |||
1480 | clone_flags = regs.regs[4]; | ||
1481 | newsp = regs.regs[5]; | ||
1482 | if (!newsp) | ||
1483 | newsp = regs.regs[29]; | ||
1484 | parent_tidptr = (int *) regs.regs[6]; | ||
1485 | |||
1486 | /* Use __dummy4 instead of getting it off the stack, so that | ||
1487 | syscall() works. */ | ||
1488 | child_tidptr = (int __user *) __dummy4; | ||
1489 | return do_fork(clone_flags, newsp, ®s, 0, | ||
1490 | parent_tidptr, child_tidptr); | ||
1491 | } | ||
1492 | |||
1493 | extern asmlinkage void sys_set_thread_area(u32 addr); | ||
1494 | asmlinkage void sys32_set_thread_area(u32 addr) | ||
1495 | { | ||
1496 | sys_set_thread_area(AA(addr)); | ||
1497 | } | ||