aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/i386/kernel/process.c20
-rw-r--r--arch/i386/kernel/smpboot.c3
-rw-r--r--include/asm-i386/processor.h12
3 files changed, 14 insertions, 21 deletions
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 5dd03757f50c..3d7e0c8e9925 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -424,18 +424,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
424 struct task_struct *tsk; 424 struct task_struct *tsk;
425 int err; 425 int err;
426 426
427 childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1; 427 childregs = task_pt_regs(p);
428 /*
429 * The below -8 is to reserve 8 bytes on top of the ring0 stack.
430 * This is necessary to guarantee that the entire "struct pt_regs"
431 * is accessable even if the CPU haven't stored the SS/ESP registers
432 * on the stack (interrupt gate does not save these registers
433 * when switching to the same priv ring).
434 * Therefore beware: accessing the xss/esp fields of the
435 * "struct pt_regs" is possible, but they may contain the
436 * completely wrong values.
437 */
438 childregs = (struct pt_regs *) ((unsigned long) childregs - 8);
439 *childregs = *regs; 428 *childregs = *regs;
440 childregs->eax = 0; 429 childregs->eax = 0;
441 childregs->esp = esp; 430 childregs->esp = esp;
@@ -540,12 +529,7 @@ EXPORT_SYMBOL(dump_thread);
540 */ 529 */
541int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) 530int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
542{ 531{
543 struct pt_regs ptregs; 532 struct pt_regs ptregs = *task_pt_regs(tsk);
544
545 ptregs = *(struct pt_regs *)
546 ((unsigned long)tsk->thread_info +
547 /* see comments in copy_thread() about -8 */
548 THREAD_SIZE - sizeof(ptregs) - 8);
549 ptregs.xcs &= 0xffff; 533 ptregs.xcs &= 0xffff;
550 ptregs.xds &= 0xffff; 534 ptregs.xds &= 0xffff;
551 ptregs.xes &= 0xffff; 535 ptregs.xes &= 0xffff;
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index a9bf5f222e47..255adb498268 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -875,8 +875,7 @@ static inline struct task_struct * alloc_idle_task(int cpu)
875 /* initialize thread_struct. we really want to avoid destroy 875 /* initialize thread_struct. we really want to avoid destroy
876 * idle tread 876 * idle tread
877 */ 877 */
878 idle->thread.esp = (unsigned long)(((struct pt_regs *) 878 idle->thread.esp = (unsigned long)task_pt_regs(idle);
879 (THREAD_SIZE + (unsigned long) idle->thread_info)) - 1);
880 init_idle(idle, cpu); 879 init_idle(idle, cpu);
881 return idle; 880 return idle;
882 } 881 }
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index 13ecf66b098c..29ad87e9123f 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -561,10 +561,20 @@ unsigned long get_wchan(struct task_struct *p);
561 (unsigned long)(&__ptr[THREAD_SIZE_LONGS]); \ 561 (unsigned long)(&__ptr[THREAD_SIZE_LONGS]); \
562}) 562})
563 563
564/*
565 * The below -8 is to reserve 8 bytes on top of the ring0 stack.
566 * This is necessary to guarantee that the entire "struct pt_regs"
567 * is accessable even if the CPU haven't stored the SS/ESP registers
568 * on the stack (interrupt gate does not save these registers
569 * when switching to the same priv ring).
570 * Therefore beware: accessing the xss/esp fields of the
571 * "struct pt_regs" is possible, but they may contain the
572 * completely wrong values.
573 */
564#define task_pt_regs(task) \ 574#define task_pt_regs(task) \
565({ \ 575({ \
566 struct pt_regs *__regs__; \ 576 struct pt_regs *__regs__; \
567 __regs__ = (struct pt_regs *)KSTK_TOP((task)->thread_info); \ 577 __regs__ = (struct pt_regs *)(KSTK_TOP((task)->thread_info)-8); \
568 __regs__ - 1; \ 578 __regs__ - 1; \
569}) 579})
570 580