diff options
-rw-r--r-- | arch/parisc/kernel/process.c | 34 |
1 files changed, 29 insertions, 5 deletions
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index 46b759385115..7fdca87ef647 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c | |||
@@ -9,7 +9,7 @@ | |||
9 | * Copyright (C) 2000-2003 Paul Bame <bame at parisc-linux.org> | 9 | * Copyright (C) 2000-2003 Paul Bame <bame at parisc-linux.org> |
10 | * Copyright (C) 2000 Philipp Rumpf <prumpf with tux.org> | 10 | * Copyright (C) 2000 Philipp Rumpf <prumpf with tux.org> |
11 | * Copyright (C) 2000 David Kennedy <dkennedy with linuxcare.com> | 11 | * Copyright (C) 2000 David Kennedy <dkennedy with linuxcare.com> |
12 | * Copyright (C) 2000 Richard Hirst <rhirst with parisc-lixux.org> | 12 | * Copyright (C) 2000 Richard Hirst <rhirst with parisc-linux.org> |
13 | * Copyright (C) 2000 Grant Grundler <grundler with parisc-linux.org> | 13 | * Copyright (C) 2000 Grant Grundler <grundler with parisc-linux.org> |
14 | * Copyright (C) 2001 Alan Modra <amodra at parisc-linux.org> | 14 | * Copyright (C) 2001 Alan Modra <amodra at parisc-linux.org> |
15 | * Copyright (C) 2001-2002 Ryan Bradetich <rbrad at parisc-linux.org> | 15 | * Copyright (C) 2001-2002 Ryan Bradetich <rbrad at parisc-linux.org> |
@@ -245,7 +245,17 @@ int | |||
245 | sys_clone(unsigned long clone_flags, unsigned long usp, | 245 | sys_clone(unsigned long clone_flags, unsigned long usp, |
246 | struct pt_regs *regs) | 246 | struct pt_regs *regs) |
247 | { | 247 | { |
248 | int __user *user_tid = (int __user *)regs->gr[26]; | 248 | /* Arugments from userspace are: |
249 | r26 = Clone flags. | ||
250 | r25 = Child stack. | ||
251 | r24 = parent_tidptr. | ||
252 | r23 = Is the TLS storage descriptor | ||
253 | r22 = child_tidptr | ||
254 | |||
255 | However, these last 3 args are only examined | ||
256 | if the proper flags are set. */ | ||
257 | int __user *child_tidptr; | ||
258 | int __user *parent_tidptr; | ||
249 | 259 | ||
250 | /* usp must be word aligned. This also prevents users from | 260 | /* usp must be word aligned. This also prevents users from |
251 | * passing in the value 1 (which is the signal for a special | 261 | * passing in the value 1 (which is the signal for a special |
@@ -253,10 +263,20 @@ sys_clone(unsigned long clone_flags, unsigned long usp, | |||
253 | usp = ALIGN(usp, 4); | 263 | usp = ALIGN(usp, 4); |
254 | 264 | ||
255 | /* A zero value for usp means use the current stack */ | 265 | /* A zero value for usp means use the current stack */ |
256 | if(usp == 0) | 266 | if (usp == 0) |
257 | usp = regs->gr[30]; | 267 | usp = regs->gr[30]; |
258 | 268 | ||
259 | return do_fork(clone_flags, usp, regs, 0, user_tid, NULL); | 269 | if (clone_flags & CLONE_PARENT_SETTID) |
270 | parent_tidptr = (int __user *)regs->gr[24]; | ||
271 | else | ||
272 | parent_tidptr = NULL; | ||
273 | |||
274 | if (clone_flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) | ||
275 | child_tidptr = (int __user *)regs->gr[22]; | ||
276 | else | ||
277 | child_tidptr = NULL; | ||
278 | |||
279 | return do_fork(clone_flags, usp, regs, 0, parent_tidptr, child_tidptr); | ||
260 | } | 280 | } |
261 | 281 | ||
262 | int | 282 | int |
@@ -332,6 +352,10 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, | |||
332 | } else { | 352 | } else { |
333 | cregs->kpc = (unsigned long) &child_return; | 353 | cregs->kpc = (unsigned long) &child_return; |
334 | } | 354 | } |
355 | /* Setup thread TLS area from the 4th parameter in clone */ | ||
356 | if (clone_flags & CLONE_SETTLS) | ||
357 | cregs->cr27 = pregs->gr[23]; | ||
358 | |||
335 | } | 359 | } |
336 | 360 | ||
337 | return 0; | 361 | return 0; |