Commit 3fc2f9e5 authored by Richard Henderson's avatar Richard Henderson

[ALPHA] Fix SETTLS -- read TLS value to install before clobbering it.

parent 788fbf37
...@@ -270,7 +270,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, ...@@ -270,7 +270,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
struct thread_info *childti = p->thread_info; struct thread_info *childti = p->thread_info;
struct pt_regs * childregs; struct pt_regs * childregs;
struct switch_stack * childstack, *stack; struct switch_stack * childstack, *stack;
unsigned long stack_offset; unsigned long stack_offset, settls;
stack_offset = PAGE_SIZE - sizeof(struct pt_regs); stack_offset = PAGE_SIZE - sizeof(struct pt_regs);
if (!(regs->ps & 8)) if (!(regs->ps & 8))
...@@ -279,6 +279,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, ...@@ -279,6 +279,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
(stack_offset + PAGE_SIZE + (long) childti); (stack_offset + PAGE_SIZE + (long) childti);
*childregs = *regs; *childregs = *regs;
settls = regs->r20;
childregs->r0 = 0; childregs->r0 = 0;
childregs->r19 = 0; childregs->r19 = 0;
childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */ childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */
...@@ -292,14 +293,16 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp, ...@@ -292,14 +293,16 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
childti->pcb.flags = 1; /* set FEN, clear everything else */ childti->pcb.flags = 1; /* set FEN, clear everything else */
/* Set a new TLS for the child thread? Peek back into the /* Set a new TLS for the child thread? Peek back into the
syscall arguments that we saved on syscall entry. */ syscall arguments that we saved on syscall entry. Oops,
except we'd have clobbered it with the parent/child set
of r20. Read the saved copy. */
/* Note: if CLONE_SETTLS is not set, then we must inherit the /* Note: if CLONE_SETTLS is not set, then we must inherit the
value from the parent, which will have been set by the block value from the parent, which will have been set by the block
copy in dup_task_struct. This is non-intuitive, but is copy in dup_task_struct. This is non-intuitive, but is
required for proper operation in the case of a threaded required for proper operation in the case of a threaded
application calling fork. */ application calling fork. */
if (clone_flags & CLONE_SETTLS) if (clone_flags & CLONE_SETTLS)
childti->pcb.unique = regs->r20; childti->pcb.unique = settls;
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment