4.14-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Andy Lutomirski <l...@kernel.org>

commit d375cf1530595e33961a8844192cddab913650e3 upstream.

On x86_64, we can easily calculate sp0 when needed instead of
storing it in thread_struct.

On x86_32, a similar cleanup would be possible, but it would require
cleaning up the vm86 code first, and that can wait for a later
cleanup series.

Signed-off-by: Andy Lutomirski <l...@kernel.org>
Cc: Borislav Petkov <bpet...@suse.de>
Cc: Brian Gerst <brge...@gmail.com>
Cc: Dave Hansen <dave.han...@intel.com>
Cc: Linus Torvalds <torva...@linux-foundation.org>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Thomas Gleixner <t...@linutronix.de>
Link: 
http://lkml.kernel.org/r/719cd9c66c548c4350d98a90f050aee8b17f8919.1509609304.git.l...@kernel.org
Signed-off-by: Ingo Molnar <mi...@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>

---
 arch/x86/include/asm/compat.h    |    1 +
 arch/x86/include/asm/processor.h |   28 +++++++++-------------------
 arch/x86/include/asm/switch_to.h |    6 ++++++
 arch/x86/kernel/process_64.c     |    1 -
 4 files changed, 16 insertions(+), 20 deletions(-)

--- a/arch/x86/include/asm/compat.h
+++ b/arch/x86/include/asm/compat.h
@@ -7,6 +7,7 @@
  */
 #include <linux/types.h>
 #include <linux/sched.h>
+#include <linux/sched/task_stack.h>
 #include <asm/processor.h>
 #include <asm/user32.h>
 #include <asm/unistd.h>
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -431,7 +431,9 @@ typedef struct {
 struct thread_struct {
        /* Cached TLS descriptors: */
        struct desc_struct      tls_array[GDT_ENTRY_TLS_ENTRIES];
+#ifdef CONFIG_X86_32
        unsigned long           sp0;
+#endif
        unsigned long           sp;
 #ifdef CONFIG_X86_32
        unsigned long           sysenter_cs;
@@ -798,6 +800,13 @@ static inline void spin_lock_prefetch(co
 
 #define task_top_of_stack(task) ((unsigned long)(task_pt_regs(task) + 1))
 
+#define task_pt_regs(task) \
+({                                                                     \
+       unsigned long __ptr = (unsigned long)task_stack_page(task);     \
+       __ptr += THREAD_SIZE - TOP_OF_KERNEL_STACK_PADDING;             \
+       ((struct pt_regs *)__ptr) - 1;                                  \
+})
+
 #ifdef CONFIG_X86_32
 /*
  * User space process size: 3GB (default).
@@ -817,23 +826,6 @@ static inline void spin_lock_prefetch(co
        .addr_limit             = KERNEL_DS,                              \
 }
 
-/*
- * TOP_OF_KERNEL_STACK_PADDING reserves 8 bytes on top of the ring0 stack.
- * This is necessary to guarantee that the entire "struct pt_regs"
- * is accessible even if the CPU haven't stored the SS/ESP registers
- * on the stack (interrupt gate does not save these registers
- * when switching to the same priv ring).
- * Therefore beware: accessing the ss/esp fields of the
- * "struct pt_regs" is possible, but they may contain the
- * completely wrong values.
- */
-#define task_pt_regs(task) \
-({                                                                     \
-       unsigned long __ptr = (unsigned long)task_stack_page(task);     \
-       __ptr += THREAD_SIZE - TOP_OF_KERNEL_STACK_PADDING;             \
-       ((struct pt_regs *)__ptr) - 1;                                  \
-})
-
 #define KSTK_ESP(task)         (task_pt_regs(task)->sp)
 
 #else
@@ -867,11 +859,9 @@ static inline void spin_lock_prefetch(co
 #define STACK_TOP_MAX          TASK_SIZE_MAX
 
 #define INIT_THREAD  {                                         \
-       .sp0                    = TOP_OF_INIT_STACK,            \
        .addr_limit             = KERNEL_DS,                    \
 }
 
-#define task_pt_regs(tsk)      ((struct pt_regs *)(tsk)->thread.sp0 - 1)
 extern unsigned long KSTK_ESP(struct task_struct *task);
 
 #endif /* CONFIG_X86_64 */
--- a/arch/x86/include/asm/switch_to.h
+++ b/arch/x86/include/asm/switch_to.h
@@ -2,6 +2,8 @@
 #ifndef _ASM_X86_SWITCH_TO_H
 #define _ASM_X86_SWITCH_TO_H
 
+#include <linux/sched/task_stack.h>
+
 struct task_struct; /* one of the stranger aspects of C forward declarations */
 
 struct task_struct *__switch_to_asm(struct task_struct *prev,
@@ -88,7 +90,11 @@ static inline void refresh_sysenter_cs(s
 /* This is used when switching tasks or entering/exiting vm86 mode. */
 static inline void update_sp0(struct task_struct *task)
 {
+#ifdef CONFIG_X86_32
        load_sp0(task->thread.sp0);
+#else
+       load_sp0(task_top_of_stack(task));
+#endif
 }
 
 #endif /* _ASM_X86_SWITCH_TO_H */
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -274,7 +274,6 @@ int copy_thread_tls(unsigned long clone_
        struct inactive_task_frame *frame;
        struct task_struct *me = current;
 
-       p->thread.sp0 = (unsigned long)task_stack_page(p) + THREAD_SIZE;
        childregs = task_pt_regs(p);
        fork_frame = container_of(childregs, struct fork_frame, regs);
        frame = &fork_frame->frame;


Reply via email to