diff options
Diffstat (limited to 'arch/i386/kernel/process.c')
-rw-r--r-- | arch/i386/kernel/process.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index c36fedf40e95..36145efc61b5 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c | |||
@@ -405,7 +405,17 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, | |||
405 | childregs->esp = esp; | 405 | childregs->esp = esp; |
406 | 406 | ||
407 | p->thread.esp = (unsigned long) childregs; | 407 | p->thread.esp = (unsigned long) childregs; |
408 | p->thread.esp0 = (unsigned long) (childregs+1); | 408 | /* |
409 | * The below -8 is to reserve 8 bytes on top of the ring0 stack. | ||
410 | * This is necessary to guarantee that the entire "struct pt_regs" | ||
411 | * is accessable even if the CPU haven't stored the SS/ESP registers | ||
412 | * on the stack (interrupt gate does not save these registers | ||
413 | * when switching to the same priv ring). | ||
414 | * Therefore beware: accessing the xss/esp fields of the | ||
415 | * "struct pt_regs" is possible, but they may contain the | ||
416 | * completely wrong values. | ||
417 | */ | ||
418 | p->thread.esp0 = (unsigned long) (childregs+1) - 8; | ||
409 | 419 | ||
410 | p->thread.eip = (unsigned long) ret_from_fork; | 420 | p->thread.eip = (unsigned long) ret_from_fork; |
411 | 421 | ||