Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4f7a1812 authored by Russell King's avatar Russell King
Browse files

[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: default avatarRussell King <rmk@arm.linux.org.uk>
parent 897f5ab2
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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
+12 −13
Original line number Diff line number Diff line
@@ -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))
+1 −1
Original line number Diff line number Diff line
@@ -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");
+2 −1
Original line number Diff line number Diff line
@@ -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);
	}
+2 −1
Original line number Diff line number Diff line
@@ -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

Loading