x86: Drop task from thread_info, add accessor functions

Add accessor functions to get a thread_info from a task_struct, and
vice-versa.  This also allows the task_struct pointer to be dropped
from thread_info altogether.

This patch also adds some accessor functions to some of the thread_info
fields, mainly for ones that are derived from a task_struct to begin
with.

Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index 4df3437..8168ddf 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -23,7 +23,9 @@
 #include <linux/atomic.h>
 
 struct thread_info {
+#ifndef CONFIG_ARCH_TASK_THREAD_MERGED
 	struct task_struct	*task;		/* main task structure */
+#endif
 	struct exec_domain	*exec_domain;	/* execution domain */
 	__u32			flags;		/* low level flags */
 	__u32			status;		/* thread synchronous flags */
@@ -42,6 +44,19 @@
 	unsigned int		uaccess_err:1;	/* uaccess failed */
 };
 
+#ifdef CONFIG_ARCH_TASK_THREAD_MERGED
+#define INIT_THREAD_INFO(tsk)			\
+{						\
+	.exec_domain	= &default_exec_domain,	\
+	.flags		= 0,			\
+	.cpu		= 0,			\
+	.saved_preempt_count = INIT_PREEMPT_COUNT,	\
+	.addr_limit	= KERNEL_DS,		\
+	.restart_block = {			\
+		.fn = do_no_restart_syscall,	\
+	},					\
+}
+#else /* CONFIG_ARCH_TASK_THREAD_MERGED */
 #define INIT_THREAD_INFO(tsk)			\
 {						\
 	.task		= &tsk,			\
@@ -54,6 +69,7 @@
 		.fn = do_no_restart_syscall,	\
 	},					\
 }
+#endif /* CONFIG_ARCH_TASK_THREAD_MERGED */
 
 #ifndef CONFIG_ARCH_TASK_THREAD_MERGED
 #define init_thread_info	(init_thread_union.thread_info)
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
index d9c12d3..b0869a6 100644
--- a/arch/x86/kernel/dumpstack.c
+++ b/arch/x86/kernel/dumpstack.c
@@ -49,7 +49,11 @@
 	if (addr != (unsigned long)return_to_handler)
 		return;
 
+#ifdef CONFIG_ARCH_TASK_THREAD_MERGED
+	task = thread_info_task(tinfo);
+#else /* CONFIG_ARCH_TASK_THREAD_MERGED */
 	task = tinfo->task;
+#endif /* CONFIG_ARCH_TASK_THREAD_MERGED */
 	index = task->curr_ret_stack;
 
 	if (!task->ret_stack || index < *graph)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 4902ef1..edada59 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2529,16 +2529,37 @@
 
 	return &tsk_ti->thread_info;
 }
+
+static inline struct task_struct *thread_info_task(const struct thread_info *ti)
+{
+	struct task_thread_struct *tsk_ti;
+
+	tsk_ti = container_of(ti, struct task_thread_struct, thread_info);
+
+	return &tsk_ti->task;
+}
+static inline struct exec_domain *get_task_exec_domain(const struct task_struct *task)
+{
+	return task_thread_info(task)->exec_domain;
+}
+
+static inline struct exec_domain *get_ti_exec_domain(const struct thread_info *ti)
+{
+	return ti->exec_domain;
+}
 #else
 #define task_thread_info(task)	((struct thread_info *)(task)->stack)
-// change ->stack member to audit locations
-#endif
+#endif /* CONFIG_ARCH_TASK_THREAD_MERGED */
 #define task_stack_page(task)	((task)->stack)
 
 static inline void setup_thread_stack(struct task_struct *p, struct task_struct *org)
 {
 	*task_thread_info(p) = *task_thread_info(org);
+#ifdef CONFIG_ARCH_TASK_THREAD_MERGED
+	*thread_info_task(task_thread_info(p)) = *p;
+#else
 	task_thread_info(p)->task = p;
+#endif
 }
 
 static inline unsigned long *end_of_stack(struct task_struct *p)
diff --git a/kernel/exec_domain.c b/kernel/exec_domain.c
index 0dbeae3..c41fc26 100644
--- a/kernel/exec_domain.c
+++ b/kernel/exec_domain.c
@@ -49,8 +49,13 @@
 {
 	set_personality(0);
 
+#ifdef CONFIG_ARCH_TASK_THREAD_MERGED
+	if (get_ti_exec_domain(current_thread_info())->handler != default_handler)
+		get_ti_exec_domain(current_thread_info())->handler(segment, regp);
+#else /* CONFIG_ARCH_TASK_THREAD_MERGED */
 	if (current_thread_info()->exec_domain->handler != default_handler)
 		current_thread_info()->exec_domain->handler(segment, regp);
+#endif /* CONFIG_ARCH_TASK_THREAD_MERGED */
 	else
 		send_sig(SIGSEGV, current, 1);
 }
@@ -136,9 +141,17 @@
 
 int __set_personality(unsigned int personality)
 {
+#ifdef CONFIG_ARCH_TASK_THREAD_MERGED
+	struct exec_domain *oep = get_ti_exec_domain(current_thread_info());
+#else /* CONFIG_ARCH_TASK_THREAD_MERGED */
 	struct exec_domain *oep = current_thread_info()->exec_domain;
+#endif /* CONFIG_ARCH_TASK_THREAD_MERGED */
 
+#ifdef CONFIG_ARCH_TASK_THREAD_MERGED
+	*get_ti_exec_domain(current_thread_info()) = *lookup_exec_domain(personality);
+#else /* CONFIG_ARCH_TASK_THREAD_MERGED */
 	current_thread_info()->exec_domain = lookup_exec_domain(personality);
+#endif /* CONFIG_ARCH_TASK_THREAD_MERGED */
 	current->personality = personality;
 	module_put(oep->module);
 
diff --git a/kernel/exit.c b/kernel/exit.c
index 601a2e8..a77a38d 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -806,7 +806,11 @@
 	if (group_dead)
 		disassociate_ctty(1);
 
+#ifdef CONFIG_ARCH_TASK_THREAD_MERGED
+	module_put(get_task_exec_domain(tsk)->module);
+#else /* CONFIG_ARCH_TASK_THREAD_MERGED */
 	module_put(task_thread_info(tsk)->exec_domain->module);
+#endif /* CONFIG_ARCH_TASK_THREAD_MERGED */
 
 	proc_exit_connector(tsk);
 
diff --git a/kernel/fork.c b/kernel/fork.c
index 73395a5..a2e17d7 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1147,10 +1147,6 @@
 					int trace)
 {
 	int retval;
-	// XXX - should be struct task_thread_struct *p
-#ifdef CONFIG_ARCH_TASK_THREAD_MERGED
-	struct thread_info *ti;
-#endif
 	struct task_struct *p;
 
 	if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
@@ -1239,9 +1235,7 @@
 
 #ifdef CONFIG_ARCH_TASK_THREAD_MERGED
 printk(KERN_INFO "pjw: before task_thread_info()\n");
-	ti = task_thread_info(p);
-	/* XXX - fixme accessors please */
-	if (!try_module_get(ti->exec_domain->module))
+	if (!try_module_get(get_task_exec_domain(p)->module))
 		goto bad_fork_cleanup_count;
 #else /* CONFIG_ARCH_TASK_THREAD_MERGED */
 	if (!try_module_get(task_thread_info(p)->exec_domain->module))
@@ -1556,7 +1550,11 @@
 		threadgroup_change_end(current);
 	cgroup_exit(p, 0);
 	delayacct_tsk_free(p);
+#ifdef CONFIG_ARCH_TASK_THREAD_MERGED
+	module_put(get_task_exec_domain(p)->module);
+#else /* CONFIG_ARCH_TASK_THREAD_MERGED */
 	module_put(task_thread_info(p)->exec_domain->module);
+#endif /* CONFIG_ARCH_TASK_THREAD_MERGED */
 bad_fork_cleanup_count:
 	atomic_dec(&p->cred->user->processes);
 	exit_creds(p);