diff options
Diffstat (limited to 'arch/parisc/kernel/process.c')
| -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; |
