diff options
author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2005-05-05 08:11:00 -0400 |
---|---|---|
committer | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2005-05-05 08:11:00 -0400 |
commit | 4f7a18124c1a44858fb74a1c4234015009952959 (patch) | |
tree | 978f55875b776c83ebcfed24737784ac098d1a4e | |
parent | 897f5ab2cd733a77a2279268262919caa8154b9d (diff) |
[PATCH] ARM: Fix kernel stack offset calculations
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>
-rw-r--r-- | arch/arm/kernel/head.S | 3 | ||||
-rw-r--r-- | arch/arm/kernel/process.c | 25 | ||||
-rw-r--r-- | arch/arm/kernel/sys_arm.c | 2 | ||||
-rw-r--r-- | arch/arm/kernel/traps.c | 3 | ||||
-rw-r--r-- | arch/arm/kernel/vmlinux.lds.S | 3 | ||||
-rw-r--r-- | include/asm-arm/processor.h | 7 | ||||
-rw-r--r-- | include/asm-arm/thread_info.h | 6 |
7 files changed, 26 insertions, 23 deletions
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 171b3e811c..4733877296 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <asm/procinfo.h> | 19 | #include <asm/procinfo.h> |
20 | #include <asm/ptrace.h> | 20 | #include <asm/ptrace.h> |
21 | #include <asm/constants.h> | 21 | #include <asm/constants.h> |
22 | #include <asm/thread_info.h> | ||
22 | #include <asm/system.h> | 23 | #include <asm/system.h> |
23 | 24 | ||
24 | #define PROCINFO_MMUFLAGS 8 | 25 | #define PROCINFO_MMUFLAGS 8 |
@@ -131,7 +132,7 @@ __switch_data: | |||
131 | .long processor_id @ r4 | 132 | .long processor_id @ r4 |
132 | .long __machine_arch_type @ r5 | 133 | .long __machine_arch_type @ r5 |
133 | .long cr_alignment @ r6 | 134 | .long cr_alignment @ r6 |
134 | .long init_thread_union+8192 @ sp | 135 | .long init_thread_union + THREAD_START_SP @ sp |
135 | 136 | ||
136 | /* | 137 | /* |
137 | * The following fragment of code is executed with the MMU on, and uses | 138 | * The following fragment of code is executed with the MMU on, and uses |
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 26eacd3e5d..8f146a4b47 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c | |||
@@ -256,8 +256,6 @@ static unsigned long *thread_info_head; | |||
256 | static unsigned int nr_thread_info; | 256 | static unsigned int nr_thread_info; |
257 | 257 | ||
258 | #define EXTRA_TASK_STRUCT 4 | 258 | #define EXTRA_TASK_STRUCT 4 |
259 | #define ll_alloc_task_struct() ((struct thread_info *) __get_free_pages(GFP_KERNEL,1)) | ||
260 | #define ll_free_task_struct(p) free_pages((unsigned long)(p),1) | ||
261 | 259 | ||
262 | struct thread_info *alloc_thread_info(struct task_struct *task) | 260 | struct thread_info *alloc_thread_info(struct task_struct *task) |
263 | { | 261 | { |
@@ -274,17 +272,16 @@ struct thread_info *alloc_thread_info(struct task_struct *task) | |||
274 | } | 272 | } |
275 | 273 | ||
276 | if (!thread) | 274 | if (!thread) |
277 | thread = ll_alloc_task_struct(); | 275 | thread = (struct thread_info *) |
276 | __get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER); | ||
278 | 277 | ||
279 | #ifdef CONFIG_MAGIC_SYSRQ | 278 | #ifdef CONFIG_DEBUG_STACK_USAGE |
280 | /* | 279 | /* |
281 | * The stack must be cleared if you want SYSRQ-T to | 280 | * The stack must be cleared if you want SYSRQ-T to |
282 | * give sensible stack usage information | 281 | * give sensible stack usage information |
283 | */ | 282 | */ |
284 | if (thread) { | 283 | if (thread) |
285 | char *p = (char *)thread; | 284 | memzero(thread, THREAD_SIZE); |
286 | memzero(p+KERNEL_STACK_SIZE, KERNEL_STACK_SIZE); | ||
287 | } | ||
288 | #endif | 285 | #endif |
289 | return thread; | 286 | return thread; |
290 | } | 287 | } |
@@ -297,7 +294,7 @@ void free_thread_info(struct thread_info *thread) | |||
297 | thread_info_head = p; | 294 | thread_info_head = p; |
298 | nr_thread_info += 1; | 295 | nr_thread_info += 1; |
299 | } else | 296 | } else |
300 | ll_free_task_struct(thread); | 297 | free_pages((unsigned long)thread, THREAD_SIZE_ORDER); |
301 | } | 298 | } |
302 | 299 | ||
303 | /* | 300 | /* |
@@ -350,7 +347,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long stack_start, | |||
350 | struct thread_info *thread = p->thread_info; | 347 | struct thread_info *thread = p->thread_info; |
351 | struct pt_regs *childregs; | 348 | struct pt_regs *childregs; |
352 | 349 | ||
353 | childregs = ((struct pt_regs *)((unsigned long)thread + THREAD_SIZE - 8)) - 1; | 350 | childregs = ((struct pt_regs *)((unsigned long)thread + THREAD_START_SP)) - 1; |
354 | *childregs = *regs; | 351 | *childregs = *regs; |
355 | childregs->ARM_r0 = 0; | 352 | childregs->ARM_r0 = 0; |
356 | childregs->ARM_sp = stack_start; | 353 | childregs->ARM_sp = stack_start; |
@@ -447,15 +444,17 @@ EXPORT_SYMBOL(kernel_thread); | |||
447 | unsigned long get_wchan(struct task_struct *p) | 444 | unsigned long get_wchan(struct task_struct *p) |
448 | { | 445 | { |
449 | unsigned long fp, lr; | 446 | unsigned long fp, lr; |
450 | unsigned long stack_page; | 447 | unsigned long stack_start, stack_end; |
451 | int count = 0; | 448 | int count = 0; |
452 | if (!p || p == current || p->state == TASK_RUNNING) | 449 | if (!p || p == current || p->state == TASK_RUNNING) |
453 | return 0; | 450 | return 0; |
454 | 451 | ||
455 | stack_page = 4096 + (unsigned long)p->thread_info; | 452 | stack_start = (unsigned long)(p->thread_info + 1); |
453 | stack_end = ((unsigned long)p->thread_info) + THREAD_SIZE; | ||
454 | |||
456 | fp = thread_saved_fp(p); | 455 | fp = thread_saved_fp(p); |
457 | do { | 456 | do { |
458 | if (fp < stack_page || fp > 4092+stack_page) | 457 | if (fp < stack_start || fp > stack_end) |
459 | return 0; | 458 | return 0; |
460 | lr = pc_pointer (((unsigned long *)fp)[-1]); | 459 | lr = pc_pointer (((unsigned long *)fp)[-1]); |
461 | if (!in_sched_functions(lr)) | 460 | if (!in_sched_functions(lr)) |
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c index ef32577da3..f897ce2ccf 100644 --- a/arch/arm/kernel/sys_arm.c +++ b/arch/arm/kernel/sys_arm.c | |||
@@ -302,7 +302,7 @@ long execve(const char *filename, char **argv, char **envp) | |||
302 | "b ret_to_user" | 302 | "b ret_to_user" |
303 | : | 303 | : |
304 | : "r" (current_thread_info()), | 304 | : "r" (current_thread_info()), |
305 | "Ir" (THREAD_SIZE - 8 - sizeof(regs)), | 305 | "Ir" (THREAD_START_SP - sizeof(regs)), |
306 | "r" (®s), | 306 | "r" (®s), |
307 | "Ir" (sizeof(regs)) | 307 | "Ir" (sizeof(regs)) |
308 | : "r0", "r1", "r2", "r3", "ip", "memory"); | 308 | : "r0", "r1", "r2", "r3", "ip", "memory"); |
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 3a001fe554..8988c02119 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c | |||
@@ -218,7 +218,8 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err) | |||
218 | tsk->comm, tsk->pid, tsk->thread_info + 1); | 218 | tsk->comm, tsk->pid, tsk->thread_info + 1); |
219 | 219 | ||
220 | if (!user_mode(regs) || in_interrupt()) { | 220 | if (!user_mode(regs) || in_interrupt()) { |
221 | dump_mem("Stack: ", regs->ARM_sp, 8192+(unsigned long)tsk->thread_info); | 221 | dump_mem("Stack: ", regs->ARM_sp, |
222 | THREAD_SIZE + (unsigned long)tsk->thread_info); | ||
222 | dump_backtrace(regs, tsk); | 223 | dump_backtrace(regs, tsk); |
223 | dump_instr(regs); | 224 | dump_instr(regs); |
224 | } | 225 | } |
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index a39c6a42d6..ad2d66c93a 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S | |||
@@ -5,6 +5,7 @@ | |||
5 | 5 | ||
6 | #include <asm-generic/vmlinux.lds.h> | 6 | #include <asm-generic/vmlinux.lds.h> |
7 | #include <linux/config.h> | 7 | #include <linux/config.h> |
8 | #include <asm/thread_info.h> | ||
8 | 9 | ||
9 | OUTPUT_ARCH(arm) | 10 | OUTPUT_ARCH(arm) |
10 | ENTRY(stext) | 11 | ENTRY(stext) |
@@ -103,7 +104,7 @@ SECTIONS | |||
103 | __data_loc = ALIGN(4); /* location in binary */ | 104 | __data_loc = ALIGN(4); /* location in binary */ |
104 | . = DATAADDR; | 105 | . = DATAADDR; |
105 | #else | 106 | #else |
106 | . = ALIGN(8192); | 107 | . = ALIGN(THREAD_SIZE); |
107 | __data_loc = .; | 108 | __data_loc = .; |
108 | #endif | 109 | #endif |
109 | 110 | ||
diff --git a/include/asm-arm/processor.h b/include/asm-arm/processor.h index 4a9845997a..7d4118e090 100644 --- a/include/asm-arm/processor.h +++ b/include/asm-arm/processor.h | |||
@@ -23,8 +23,6 @@ | |||
23 | #include <asm/procinfo.h> | 23 | #include <asm/procinfo.h> |
24 | #include <asm/types.h> | 24 | #include <asm/types.h> |
25 | 25 | ||
26 | #define KERNEL_STACK_SIZE PAGE_SIZE | ||
27 | |||
28 | union debug_insn { | 26 | union debug_insn { |
29 | u32 arm; | 27 | u32 arm; |
30 | u16 thumb; | 28 | u16 thumb; |
@@ -87,8 +85,9 @@ unsigned long get_wchan(struct task_struct *p); | |||
87 | */ | 85 | */ |
88 | extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | 86 | extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); |
89 | 87 | ||
90 | #define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)->thread_info))[1019]) | 88 | #define KSTK_REGS(tsk) (((struct pt_regs *)(THREAD_START_SP + (unsigned long)(tsk)->thread_info)) - 1) |
91 | #define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)->thread_info))[1017]) | 89 | #define KSTK_EIP(tsk) KSTK_REGS(tsk)->ARM_pc |
90 | #define KSTK_ESP(tsk) KSTK_REGS(tsk)->ARM_sp | ||
92 | 91 | ||
93 | /* | 92 | /* |
94 | * Prefetching support - only ARMv5. | 93 | * Prefetching support - only ARMv5. |
diff --git a/include/asm-arm/thread_info.h b/include/asm-arm/thread_info.h index a61618fb43..66c585c50c 100644 --- a/include/asm-arm/thread_info.h +++ b/include/asm-arm/thread_info.h | |||
@@ -14,6 +14,10 @@ | |||
14 | 14 | ||
15 | #include <asm/fpstate.h> | 15 | #include <asm/fpstate.h> |
16 | 16 | ||
17 | #define THREAD_SIZE_ORDER 1 | ||
18 | #define THREAD_SIZE 8192 | ||
19 | #define THREAD_START_SP (THREAD_SIZE - 8) | ||
20 | |||
17 | #ifndef __ASSEMBLY__ | 21 | #ifndef __ASSEMBLY__ |
18 | 22 | ||
19 | struct task_struct; | 23 | struct task_struct; |
@@ -77,8 +81,6 @@ struct thread_info { | |||
77 | #define init_thread_info (init_thread_union.thread_info) | 81 | #define init_thread_info (init_thread_union.thread_info) |
78 | #define init_stack (init_thread_union.stack) | 82 | #define init_stack (init_thread_union.stack) |
79 | 83 | ||
80 | #define THREAD_SIZE 8192 | ||
81 | |||
82 | /* | 84 | /* |
83 | * how to get the thread information struct from C | 85 | * how to get the thread information struct from C |
84 | */ | 86 | */ |