x86: continued work on thread_info separation from stack

More work on this.

Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index 4299eb0..85c98a8 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -135,7 +135,12 @@
 	CFI_REL_OFFSET rsp,0
 	pushfq_cfi
 	/*CFI_REL_OFFSET rflags,0*/
+#ifdef CONFIG_ARCH_TASK_THREAD_MERGED
+	GET_THREAD_INFO(%rcx)
+	movl	TI_sysenter_return(%rcx),%r10d
+#else
 	movl	TI_sysenter_return+THREAD_INFO(%rsp,3*8-KERNEL_STACK_OFFSET),%r10d
+#endif
 	CFI_REGISTER rip,r10
 	pushq_cfi $__USER32_CS
 	/*CFI_REL_OFFSET cs,0*/
@@ -151,8 +156,14 @@
 1:	movl	(%rbp),%ebp
 	_ASM_EXTABLE(1b,ia32_badarg)
 	ASM_CLAC
+#ifdef CONFIG_ARCH_TASK_THREAD_MERGED
+	GET_THREAD_INFO(%rcx)
+	orl     $TS_COMPAT,TI_status(%rcx)
+	testl   $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%rcx)
+#else
 	orl     $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET)
 	testl   $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
+#endif
 	CFI_REMEMBER_STATE
 	jnz  sysenter_tracesys
 	cmpq	$(IA32_NR_syscalls-1),%rax
@@ -164,10 +175,20 @@
 	movq	%rax,RAX-ARGOFFSET(%rsp)
 	DISABLE_INTERRUPTS(CLBR_NONE)
 	TRACE_IRQS_OFF
+#ifdef CONFIG_ARCH_TASK_THREAD_MERGED
+	GET_THREAD_INFO(%rcx)
+	testl	$_TIF_ALLWORK_MASK,TI_flags(%rcx)
+#else
 	testl	$_TIF_ALLWORK_MASK,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
+#endif
 	jnz	sysexit_audit
 sysexit_from_sys_call:
+#ifdef CONFIG_ARCH_TASK_THREAD_MERGED
+	GET_THREAD_INFO(%rcx)
+	andl    $~TS_COMPAT,TI_status(%rcx)
+#else
 	andl    $~TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET)
+#endif
 	/* clear IF, that popfq doesn't enable interrupts early */
 	andl  $~0x200,EFLAGS-R11(%rsp) 
 	movl	RIP-R11(%rsp),%edx		/* User %eip */
@@ -204,7 +225,12 @@
 	.endm
 
 	.macro auditsys_exit exit
+#ifdef CONFIG_ARCH_TASK_THREAD_MERGED
+	GET_THREAD_INFO(%rcx)
+	testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),TI_flags(%rcx)
+#else
 	testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
+#endif
 	jnz ia32_ret_from_sys_call
 	TRACE_IRQS_ON
 	ENABLE_INTERRUPTS(CLBR_NONE)
@@ -219,7 +245,12 @@
 	movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi
 	DISABLE_INTERRUPTS(CLBR_NONE)
 	TRACE_IRQS_OFF
+#ifdef CONFIG_ARCH_TASK_THREAD_MERGED
+	GET_THREAD_INFO(%rcx)
+	testl %edi,TI_flags(%rcx)
+#else
 	testl %edi,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
+#endif
 	jz \exit
 	CLEAR_RREGS -ARGOFFSET
 	jmp int_with_check
@@ -237,7 +268,12 @@
 
 sysenter_tracesys:
 #ifdef CONFIG_AUDITSYSCALL
+#ifdef CONFIG_ARCH_TASK_THREAD_MERGED
+	GET_THREAD_INFO(%rcx)
+	testl	$(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%rcx)
+#else
 	testl	$(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
+#endif
 	jz	sysenter_auditsys
 #endif
 	SAVE_REST
@@ -308,8 +344,14 @@
 1:	movl	(%r8),%r9d
 	_ASM_EXTABLE(1b,ia32_badarg)
 	ASM_CLAC
+#ifdef CONFIG_ARCH_TASK_THREAD_MERGED
+	GET_THREAD_INFO(%rcx)
+	orl     $TS_COMPAT,TI_status(%rcx)
+	testl   $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%rcx)
+#else
 	orl     $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET)
 	testl   $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
+#endif
 	CFI_REMEMBER_STATE
 	jnz   cstar_tracesys
 	cmpq $IA32_NR_syscalls-1,%rax
@@ -321,10 +363,20 @@
 	movq %rax,RAX-ARGOFFSET(%rsp)
 	DISABLE_INTERRUPTS(CLBR_NONE)
 	TRACE_IRQS_OFF
+#ifdef CONFIG_ARCH_TASK_THREAD_MERGED
+	GET_THREAD_INFO(%rcx)
+	testl $_TIF_ALLWORK_MASK,TI_flags(%rcx)
+#else
 	testl $_TIF_ALLWORK_MASK,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
+#endif
 	jnz sysretl_audit
 sysretl_from_sys_call:
+#ifdef CONFIG_ARCH_TASK_THREAD_MERGED
+	GET_THREAD_INFO(%rcx)
+	andl $~TS_COMPAT,TI_status(%rcx)
+#else
 	andl $~TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET)
+#endif
 	RESTORE_ARGS 0,-ARG_SKIP,0,0,0
 	movl RIP-ARGOFFSET(%rsp),%ecx
 	CFI_REGISTER rip,rcx
@@ -352,7 +404,12 @@
 
 cstar_tracesys:
 #ifdef CONFIG_AUDITSYSCALL
+#ifdef CONFIG_ARCH_TASK_THREAD_MERGED
+	GET_THREAD_INFO(%rcx)
+	testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%rcx)
+#else
 	testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
+#endif
 	jz cstar_auditsys
 #endif
 	xchgl %r9d,%ebp
@@ -418,8 +475,14 @@
 	/* note the registers are not zero extended to the sf.
 	   this could be a problem. */
 	SAVE_ARGS 0,1,0
+#ifdef CONFIG_ARCH_TASK_THREAD_MERGED
+	GET_THREAD_INFO(%rcx)
+	orl $TS_COMPAT,TI_status(%rcx)
+	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%rcx)
+#else
 	orl $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET)
 	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
+#endif
 	jnz ia32_tracesys
 	cmpq $(IA32_NR_syscalls-1),%rax
 	ja ia32_badsys
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index ff3adc0..dda23b7 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -204,21 +204,33 @@
  */
 #ifndef __ASSEMBLY__
 DECLARE_PER_CPU(unsigned long, kernel_stack);
+#ifdef CONFIG_ARCH_TASK_THREAD_MERGED
+DECLARE_PER_CPU(struct thread_info *, current_ti);
+#endif
 
 static inline struct thread_info *current_thread_info(void)
 {
 	struct thread_info *ti;
+#ifdef CONFIG_ARCH_TASK_THREAD_MERGED
+	ti = (void *)(this_cpu_read_stable(current_ti));
+#else
 	ti = (void *)(this_cpu_read_stable(kernel_stack) +
 		      KERNEL_STACK_OFFSET - THREAD_SIZE);
+#endif
 	return ti;
 }
 
 #else /* !__ASSEMBLY__ */
 
 /* how to get the thread information struct from ASM */
+#ifdef CONFIG_ARCH_TASK_THREAD_MERGED
+#define GET_THREAD_INFO(reg) \
+	movq PER_CPU_VAR(current_ti),reg
+#else
 #define GET_THREAD_INFO(reg) \
 	movq PER_CPU_VAR(kernel_stack),reg ; \
 	subq $(THREAD_SIZE-KERNEL_STACK_OFFSET),reg
+#endif /* CONFIG_ARCH_TASK_THREAD_MERGED */
 
 /*
  * Same if PER_CPU_VAR(kernel_stack) is, perhaps with some offset, already in
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 439bbd4..fe66f13 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1095,6 +1095,10 @@
 	&GET_INIT_TASK;
 EXPORT_PER_CPU_SYMBOL(current_task);
 
+DEFINE_PER_CPU(struct thread_info *, current_ti) ____cacheline_aligned =
+	&init_task_thread.thread_info;
+EXPORT_PER_CPU_SYMBOL(current_ti);
+
 DEFINE_PER_CPU(unsigned long, kernel_stack) =
 	(unsigned long)&init_stack;
 EXPORT_PER_CPU_SYMBOL(kernel_stack);
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 1e96c36..171edb1 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -613,9 +613,15 @@
 	ENABLE_INTERRUPTS(CLBR_NONE)
 	SAVE_ARGS 8,0
 	movq  %rax,ORIG_RAX-ARGOFFSET(%rsp)
+	/* pjw XXX - probably drop this? */
 	movq  %rcx,RIP-ARGOFFSET(%rsp)
 	CFI_REL_OFFSET rip,RIP-ARGOFFSET
+#ifdef CONFIG_ARCH_TASK_THREAD_MERGED
+	GET_THREAD_INFO(%rcx)
+	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%rcx)
+#else
 	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
+#endif
 	jnz tracesys
 system_call_fastpath:
 #if __SYSCALL_MASK == ~0
@@ -639,7 +645,12 @@
 	LOCKDEP_SYS_EXIT
 	DISABLE_INTERRUPTS(CLBR_NONE)
 	TRACE_IRQS_OFF
+#ifdef CONFIG_ARCH_TASK_THREAD_MERGED
+	GET_THREAD_INFO(%rcx)
+	movl TI_flags(%rcx),%edx
+#else
 	movl TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET),%edx
+#endif
 	andl %edi,%edx
 	jnz  sysret_careful
 	CFI_REMEMBER_STATE
@@ -722,7 +733,12 @@
 	/* Do syscall tracing */
 tracesys:
 #ifdef CONFIG_AUDITSYSCALL
+#ifdef CONFIG_ARCH_TASK_THREAD_MERGED
+	GET_THREAD_INFO(%rcx)
+	testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%rcx)
+#else
 	testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
+#endif
 	jz auditsys
 #endif
 	SAVE_REST