diff options
author | akpm@osdl.org <akpm@osdl.org> | 2006-01-12 04:05:41 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-01-12 12:08:52 -0500 |
commit | 07b047fc2466249aff7cdb23fa0b0955a7a00d48 (patch) | |
tree | af22cc80470f8aff6d0c25276ef8fae2b3f537a7 | |
parent | 06b425d80f56280e698b3e8487c372e0d39d9ba1 (diff) |
[PATCH] i386: fix task_pt_regs()
)
From: Al Viro <viro@ftp.linux.org.uk>
task_pt_regs() needs the same offset-by-8 to match copy_thread()
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | arch/i386/kernel/process.c | 20 | ||||
-rw-r--r-- | arch/i386/kernel/smpboot.c | 3 | ||||
-rw-r--r-- | include/asm-i386/processor.h | 12 |
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 | */ |
541 | int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) | 530 | int 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 | ||