MN10300: Save frame pointer in thread_info struct rather than global var

Save the current exception frame pointer in the thread_info struct rather than
in a global variable as the latter makes SMP tricky, especially when preemption
is also enabled.

This also replaces __frame with current_frame() and rearranges header file
inclusions to make it all compile.

Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Akira Takeuchi <takeuchi.akr@jp.panasonic.com>
diff --git a/arch/mn10300/kernel/asm-offsets.c b/arch/mn10300/kernel/asm-offsets.c
index 54cc5b6..96f24fa 100644
--- a/arch/mn10300/kernel/asm-offsets.c
+++ b/arch/mn10300/kernel/asm-offsets.c
@@ -23,6 +23,7 @@
 
 	OFFSET(TI_task,			thread_info, task);
 	OFFSET(TI_exec_domain,		thread_info, exec_domain);
+	OFFSET(TI_frame,		thread_info, frame);
 	OFFSET(TI_flags,		thread_info, flags);
 	OFFSET(TI_cpu,			thread_info, cpu);
 	OFFSET(TI_preempt_count,	thread_info, preempt_count);
@@ -66,7 +67,6 @@
 	OFFSET(THREAD_SP,		thread_struct, sp);
 	OFFSET(THREAD_A3,		thread_struct, a3);
 	OFFSET(THREAD_USP,		thread_struct, usp);
-	OFFSET(THREAD_FRAME,		thread_struct, frame);
 #ifdef CONFIG_FPU
 	OFFSET(THREAD_FPU_FLAGS,	thread_struct, fpu_flags);
 	OFFSET(THREAD_FPU_STATE,	thread_struct, fpu_state);
diff --git a/arch/mn10300/kernel/mn10300-watchdog.c b/arch/mn10300/kernel/mn10300-watchdog.c
index 965dd61..c5e12bf 100644
--- a/arch/mn10300/kernel/mn10300-watchdog.c
+++ b/arch/mn10300/kernel/mn10300-watchdog.c
@@ -122,7 +122,7 @@
 static void watchdog_dump_register(void *dummy)
 {
 	printk(KERN_ERR "--- Register Dump (CPU%d) ---\n", CPUID);
-	show_registers(__frame);
+	show_registers(current_frame());
 }
 #endif
 
diff --git a/arch/mn10300/kernel/process.c b/arch/mn10300/kernel/process.c
index b2e85ed..0d0f804 100644
--- a/arch/mn10300/kernel/process.c
+++ b/arch/mn10300/kernel/process.c
@@ -228,6 +228,7 @@
 		unsigned long c_usp, unsigned long ustk_size,
 		struct task_struct *p, struct pt_regs *kregs)
 {
+	struct thread_info *ti = task_thread_info(p);
 	struct pt_regs *c_uregs, *c_kregs, *uregs;
 	unsigned long c_ksp;
 
@@ -248,7 +249,7 @@
 
 	/* the new TLS pointer is passed in as arg #5 to sys_clone() */
 	if (clone_flags & CLONE_SETTLS)
-		c_uregs->e2 = __frame->d3;
+		c_uregs->e2 = current_frame()->d3;
 
 	/* set up the return kernel frame if called from kernel_thread() */
 	c_kregs = c_uregs;
@@ -266,7 +267,7 @@
 	}
 
 	/* set up things up so the scheduler can start the new task */
-	p->thread.frame = c_kregs;
+	ti->frame	= c_kregs;
 	p->thread.a3	= (unsigned long) c_kregs;
 	p->thread.sp	= c_ksp;
 	p->thread.pc	= (unsigned long) ret_from_fork;
@@ -278,25 +279,26 @@
 
 /*
  * clone a process
- * - tlsptr is retrieved by copy_thread() from __frame->d3
+ * - tlsptr is retrieved by copy_thread() from current_frame()->d3
  */
 asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp,
 			  int __user *parent_tidptr, int __user *child_tidptr,
 			  int __user *tlsptr)
 {
-	return do_fork(clone_flags, newsp ?: __frame->sp, __frame, 0,
-		       parent_tidptr, child_tidptr);
+	return do_fork(clone_flags, newsp ?: current_frame()->sp,
+		       current_frame(), 0, parent_tidptr, child_tidptr);
 }
 
 asmlinkage long sys_fork(void)
 {
-	return do_fork(SIGCHLD, __frame->sp, __frame, 0, NULL, NULL);
+	return do_fork(SIGCHLD, current_frame()->sp,
+		       current_frame(), 0, NULL, NULL);
 }
 
 asmlinkage long sys_vfork(void)
 {
-	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, __frame->sp, __frame,
-		       0, NULL, NULL);
+	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, current_frame()->sp,
+		       current_frame(), 0, NULL, NULL);
 }
 
 asmlinkage long sys_execve(const char __user *name,
@@ -310,7 +312,7 @@
 	error = PTR_ERR(filename);
 	if (IS_ERR(filename))
 		return error;
-	error = do_execve(filename, argv, envp, __frame);
+	error = do_execve(filename, argv, envp, current_frame());
 	putname(filename);
 	return error;
 }
diff --git a/arch/mn10300/kernel/signal.c b/arch/mn10300/kernel/signal.c
index d4de05a..690f4e9 100644
--- a/arch/mn10300/kernel/signal.c
+++ b/arch/mn10300/kernel/signal.c
@@ -91,7 +91,7 @@
  */
 asmlinkage long sys_sigaltstack(const stack_t __user *uss, stack_t *uoss)
 {
-	return do_sigaltstack(uss, uoss, __frame->sp);
+	return do_sigaltstack(uss, uoss, current_frame()->sp);
 }
 
 /*
@@ -156,10 +156,11 @@
  */
 asmlinkage long sys_sigreturn(void)
 {
-	struct sigframe __user *frame = (struct sigframe __user *) __frame->sp;
+	struct sigframe __user *frame;
 	sigset_t set;
 	long d0;
 
+	frame = (struct sigframe __user *) current_frame()->sp;
 	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
 	if (__get_user(set.sig[0], &frame->sc.oldmask))
@@ -176,7 +177,7 @@
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 
-	if (restore_sigcontext(__frame, &frame->sc, &d0))
+	if (restore_sigcontext(current_frame(), &frame->sc, &d0))
 		goto badframe;
 
 	return d0;
@@ -191,11 +192,11 @@
  */
 asmlinkage long sys_rt_sigreturn(void)
 {
-	struct rt_sigframe __user *frame =
-		(struct rt_sigframe __user *) __frame->sp;
+	struct rt_sigframe __user *frame;
 	sigset_t set;
-	unsigned long d0;
+	long d0;
 
+	frame = (struct rt_sigframe __user *) current_frame()->sp;
 	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
 	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
@@ -207,10 +208,11 @@
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 
-	if (restore_sigcontext(__frame, &frame->uc.uc_mcontext, &d0))
+	if (restore_sigcontext(current_frame(), &frame->uc.uc_mcontext, &d0))
 		goto badframe;
 
-	if (do_sigaltstack(&frame->uc.uc_stack, NULL, __frame->sp) == -EFAULT)
+	if (do_sigaltstack(&frame->uc.uc_stack, NULL, current_frame()->sp) ==
+	    -EFAULT)
 		goto badframe;
 
 	return d0;
@@ -572,7 +574,7 @@
 
 	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
 		clear_thread_flag(TIF_NOTIFY_RESUME);
-		tracehook_notify_resume(__frame);
+		tracehook_notify_resume(current_frame());
 		if (current->replacement_session_keyring)
 			key_replace_session_keyring();
 	}
diff --git a/arch/mn10300/kernel/switch_to.S b/arch/mn10300/kernel/switch_to.S
index b08cb2e..9074d0f 100644
--- a/arch/mn10300/kernel/switch_to.S
+++ b/arch/mn10300/kernel/switch_to.S
@@ -38,15 +38,6 @@
 	mov	d1,a1
 
 	# save prev context
-#ifdef CONFIG_SMP
-	mov	(CPUID),a2
-	add	a2,a2
-	add	a2,a2
-	mov	(___frame,a2),d0
-#else  /* CONFIG_SMP */
-	mov	(__frame),d0
-#endif /* CONFIG_SMP */
-	mov	d0,(THREAD_FRAME,a0)
 	mov	__switch_back,d0
 	mov	d0,(THREAD_PC,a0)
 	mov	sp,a2
@@ -68,15 +59,6 @@
 	mov	a2,e2
 #endif
 
-	mov	(THREAD_FRAME,a1),a2
-#ifdef CONFIG_SMP
-	mov	(CPUID),a0
-	add	a0,a0
-	add	a0,a0
-	mov	a2,(___frame,a0)
-#else  /* CONFIG_SMP */
-	mov	a2,(__frame)
-#endif /* CONFIG_SMP */
 	mov	(THREAD_PC,a1),a2
 	mov	d2,d0			# for ret_from_fork
 	mov	d0,a0			# for __switch_to
diff --git a/arch/mn10300/kernel/traps.c b/arch/mn10300/kernel/traps.c
index c924a1d..b90c3f1 100644
--- a/arch/mn10300/kernel/traps.c
+++ b/arch/mn10300/kernel/traps.c
@@ -45,14 +45,6 @@
 #error "INTERRUPT_VECTOR_BASE not aligned to 16MiB boundary!"
 #endif
 
-#ifdef CONFIG_SMP
-struct pt_regs *___frame[NR_CPUS]; /* current frame pointer */
-EXPORT_SYMBOL(___frame);
-#else  /* CONFIG_SMP */
-struct pt_regs *__frame; /* current frame pointer */
-EXPORT_SYMBOL(__frame);
-#endif /* CONFIG_SMP */
-
 int kstack_depth_to_print = 24;
 
 spinlock_t die_lock = __SPIN_LOCK_UNLOCKED(die_lock);