[PATCH] ARM: Fix kernel stack offset calculations
authorRussell King <rmk@dyn-67.arm.linux.org.uk>
Thu, 5 May 2005 12:11:00 +0000 (13:11 +0100)
committerRussell King <rmk@dyn-67.arm.linux.org.uk>
Thu, 5 May 2005 12:11:00 +0000 (13:11 +0100)
Various places in the ARM kernel implicitly assumed that kernel
stacks are always 8K due to hard coded constants.  Replace these
constants with definitions.

Correct the allowable range of kernel stack pointer values within
the allocation.  Arrange for the entire kernel stack to be zeroed,
not just the upper 4K if CONFIG_DEBUG_STACK_USAGE is set.

Signed-off-by: Russell King <rmk@arm.linux.org.uk>
arch/arm/kernel/head.S
arch/arm/kernel/process.c
arch/arm/kernel/sys_arm.c
arch/arm/kernel/traps.c
arch/arm/kernel/vmlinux.lds.S
include/asm-arm/processor.h
include/asm-arm/thread_info.h

index 171b3e811c7166f20cf218266982fb895575d704..4733877296d41209f6e0b0dd6c5c66cf6a0f3762 100644 (file)
@@ -19,6 +19,7 @@
 #include <asm/procinfo.h>
 #include <asm/ptrace.h>
 #include <asm/constants.h>
+#include <asm/thread_info.h>
 #include <asm/system.h>
 
 #define PROCINFO_MMUFLAGS      8
@@ -131,7 +132,7 @@ __switch_data:
        .long   processor_id                    @ r4
        .long   __machine_arch_type             @ r5
        .long   cr_alignment                    @ r6
-       .long   init_thread_union+8192          @ sp
+       .long   init_thread_union + THREAD_START_SP @ sp
 
 /*
  * The following fragment of code is executed with the MMU on, and uses
index 26eacd3e5def130504adf2ddd88f9cc977c98abf..8f146a4b4752665013bc33c510f1df5adb53a739 100644 (file)
@@ -256,8 +256,6 @@ static unsigned long *thread_info_head;
 static unsigned int nr_thread_info;
 
 #define EXTRA_TASK_STRUCT      4
-#define ll_alloc_task_struct() ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
-#define ll_free_task_struct(p) free_pages((unsigned long)(p),1)
 
 struct thread_info *alloc_thread_info(struct task_struct *task)
 {
@@ -274,17 +272,16 @@ struct thread_info *alloc_thread_info(struct task_struct *task)
        }
 
        if (!thread)
-               thread = ll_alloc_task_struct();
+               thread = (struct thread_info *)
+                          __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER);
 
-#ifdef CONFIG_MAGIC_SYSRQ
+#ifdef CONFIG_DEBUG_STACK_USAGE
        /*
         * The stack must be cleared if you want SYSRQ-T to
         * give sensible stack usage information
         */
-       if (thread) {
-               char *p = (char *)thread;
-               memzero(p+KERNEL_STACK_SIZE, KERNEL_STACK_SIZE);
-       }
+       if (thread)
+               memzero(thread, THREAD_SIZE);
 #endif
        return thread;
 }
@@ -297,7 +294,7 @@ void free_thread_info(struct thread_info *thread)
                thread_info_head = p;
                nr_thread_info += 1;
        } else
-               ll_free_task_struct(thread);
+               free_pages((unsigned long)thread, THREAD_SIZE_ORDER);
 }
 
 /*
@@ -350,7 +347,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long stack_start,
        struct thread_info *thread = p->thread_info;
        struct pt_regs *childregs;
 
-       childregs = ((struct pt_regs *)((unsigned long)thread + THREAD_SIZE - 8)) - 1;
+       childregs = ((struct pt_regs *)((unsigned long)thread + THREAD_START_SP)) - 1;
        *childregs = *regs;
        childregs->ARM_r0 = 0;
        childregs->ARM_sp = stack_start;
@@ -447,15 +444,17 @@ EXPORT_SYMBOL(kernel_thread);
 unsigned long get_wchan(struct task_struct *p)
 {
        unsigned long fp, lr;
-       unsigned long stack_page;
+       unsigned long stack_start, stack_end;
        int count = 0;
        if (!p || p == current || p->state == TASK_RUNNING)
                return 0;
 
-       stack_page = 4096 + (unsigned long)p->thread_info;
+       stack_start = (unsigned long)(p->thread_info + 1);
+       stack_end = ((unsigned long)p->thread_info) + THREAD_SIZE;
+
        fp = thread_saved_fp(p);
        do {
-               if (fp < stack_page || fp > 4092+stack_page)
+               if (fp < stack_start || fp > stack_end)
                        return 0;
                lr = pc_pointer (((unsigned long *)fp)[-1]);
                if (!in_sched_functions(lr))
index ef32577da304ba7f4c13a9c92d0f6a36631d3376..f897ce2ccf0d358cc79a6493b23d1cf33d91a05a 100644 (file)
@@ -302,7 +302,7 @@ long execve(const char *filename, char **argv, char **envp)
                "b      ret_to_user"
                :
                : "r" (current_thread_info()),
-                 "Ir" (THREAD_SIZE - 8 - sizeof(regs)),
+                 "Ir" (THREAD_START_SP - sizeof(regs)),
                  "r" (&regs),
                  "Ir" (sizeof(regs))
                : "r0", "r1", "r2", "r3", "ip", "memory");
index 3a001fe5540badeb1b5452f9d665e747e28687a2..8988c02119fd3e2fbe0d9b98bacac2957ccc6e29 100644 (file)
@@ -218,7 +218,8 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
                tsk->comm, tsk->pid, tsk->thread_info + 1);
 
        if (!user_mode(regs) || in_interrupt()) {
-               dump_mem("Stack: ", regs->ARM_sp, 8192+(unsigned long)tsk->thread_info);
+               dump_mem("Stack: ", regs->ARM_sp,
+                        THREAD_SIZE + (unsigned long)tsk->thread_info);
                dump_backtrace(regs, tsk);
                dump_instr(regs);
        }
index a39c6a42d68ad4b6a9a8f1f3a1b3b28e54591c38..ad2d66c93a5c3edf15f7a854683c9d67bfd76241 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <asm-generic/vmlinux.lds.h>
 #include <linux/config.h>
+#include <asm/thread_info.h>
        
 OUTPUT_ARCH(arm)
 ENTRY(stext)
@@ -103,7 +104,7 @@ SECTIONS
        __data_loc = ALIGN(4);          /* location in binary */
        . = DATAADDR;
 #else
-       . = ALIGN(8192);
+       . = ALIGN(THREAD_SIZE);
        __data_loc = .;
 #endif
 
index 4a9845997a75b861dce954441f57c1c8dbc09e7c..7d4118e090542222ec87020f9840e21f121b43ec 100644 (file)
@@ -23,8 +23,6 @@
 #include <asm/procinfo.h>
 #include <asm/types.h>
 
-#define KERNEL_STACK_SIZE      PAGE_SIZE
-
 union debug_insn {
        u32     arm;
        u16     thumb;
@@ -87,8 +85,9 @@ unsigned long get_wchan(struct task_struct *p);
  */
 extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
 
-#define KSTK_EIP(tsk)  (((unsigned long *)(4096+(unsigned long)(tsk)->thread_info))[1019])
-#define KSTK_ESP(tsk)  (((unsigned long *)(4096+(unsigned long)(tsk)->thread_info))[1017])
+#define KSTK_REGS(tsk) (((struct pt_regs *)(THREAD_START_SP + (unsigned long)(tsk)->thread_info)) - 1)
+#define KSTK_EIP(tsk)  KSTK_REGS(tsk)->ARM_pc
+#define KSTK_ESP(tsk)  KSTK_REGS(tsk)->ARM_sp
 
 /*
  * Prefetching support - only ARMv5.
index a61618fb433cbe9b12bfa7d83aec0321997c33a7..66c585c50cf910c5928739272ee9057f3432fa5c 100644 (file)
 
 #include <asm/fpstate.h>
 
+#define THREAD_SIZE_ORDER      1
+#define THREAD_SIZE            8192
+#define THREAD_START_SP                (THREAD_SIZE - 8)
+
 #ifndef __ASSEMBLY__
 
 struct task_struct;
@@ -77,8 +81,6 @@ struct thread_info {
 #define init_thread_info       (init_thread_union.thread_info)
 #define init_stack             (init_thread_union.stack)
 
-#define THREAD_SIZE            8192
-
 /*
  * how to get the thread information struct from C
  */