| From b9d989c7218ac922185d82ad46f3e58b27a4bea9 Mon Sep 17 00:00:00 2001 |
| From: Andy Lutomirski <luto@kernel.org> |
| Date: Tue, 13 Sep 2016 14:29:21 -0700 |
| Subject: [PATCH] x86/asm: Move the thread_info::status field to thread_struct |
| |
| commit b9d989c7218ac922185d82ad46f3e58b27a4bea9 upstream. |
| |
| Because sched.h and thread_info.h are a tangled mess, I turned |
| in_compat_syscall() into a macro. If we had current_thread_struct() |
| or similar and we could use it from thread_info.h, then this would |
| be a bit cleaner. |
| |
| Signed-off-by: Andy Lutomirski <luto@kernel.org> |
| Cc: Borislav Petkov <bp@alien8.de> |
| Cc: Brian Gerst <brgerst@gmail.com> |
| Cc: Denys Vlasenko <dvlasenk@redhat.com> |
| Cc: H. Peter Anvin <hpa@zytor.com> |
| Cc: Jann Horn <jann@thejh.net> |
| Cc: Josh Poimboeuf <jpoimboe@redhat.com> |
| Cc: Linus Torvalds <torvalds@linux-foundation.org> |
| Cc: Peter Zijlstra <peterz@infradead.org> |
| Cc: Thomas Gleixner <tglx@linutronix.de> |
| Link: http://lkml.kernel.org/r/ccc8a1b2f41f9c264a41f771bb4a6539a642ad72.1473801993.git.luto@kernel.org |
| Signed-off-by: Ingo Molnar <mingo@kernel.org> |
| |
| diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c |
| index 1433f6b4607d..871bbf975d4c 100644 |
| --- a/arch/x86/entry/common.c |
| +++ b/arch/x86/entry/common.c |
| @@ -209,7 +209,7 @@ __visible inline void prepare_exit_to_usermode(struct pt_regs *regs) |
| * special case only applies after poking regs and before the |
| * very next return to user mode. |
| */ |
| - ti->status &= ~(TS_COMPAT|TS_I386_REGS_POKED); |
| + current->thread.status &= ~(TS_COMPAT|TS_I386_REGS_POKED); |
| #endif |
| |
| user_enter_irqoff(); |
| @@ -307,7 +307,7 @@ static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs) |
| unsigned int nr = (unsigned int)regs->orig_ax; |
| |
| #ifdef CONFIG_IA32_EMULATION |
| - ti->status |= TS_COMPAT; |
| + current->thread.status |= TS_COMPAT; |
| #endif |
| |
| if (READ_ONCE(ti->flags) & _TIF_WORK_SYSCALL_ENTRY) { |
| diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h |
| index b22fb5a4ff3c..984a7bf17f6a 100644 |
| --- a/arch/x86/include/asm/processor.h |
| +++ b/arch/x86/include/asm/processor.h |
| @@ -389,6 +389,9 @@ struct thread_struct { |
| unsigned short fsindex; |
| unsigned short gsindex; |
| #endif |
| + |
| + u32 status; /* thread synchronous flags */ |
| + |
| #ifdef CONFIG_X86_64 |
| unsigned long fsbase; |
| unsigned long gsbase; |
| @@ -434,6 +437,15 @@ struct thread_struct { |
| */ |
| }; |
| |
| +/* |
| + * Thread-synchronous status. |
| + * |
| + * This is different from the flags in that nobody else |
| + * ever touches our thread-synchronous status, so we don't |
| + * have to worry about atomic accesses. |
| + */ |
| +#define TS_COMPAT 0x0002 /* 32bit syscall active (64BIT)*/ |
| + |
| /* |
| * Set IOPL bits in EFLAGS from given mask |
| */ |
| diff --git a/arch/x86/include/asm/syscall.h b/arch/x86/include/asm/syscall.h |
| index 4e23dd15c661..e3c95e8e61c5 100644 |
| --- a/arch/x86/include/asm/syscall.h |
| +++ b/arch/x86/include/asm/syscall.h |
| @@ -60,7 +60,7 @@ static inline long syscall_get_error(struct task_struct *task, |
| * TS_COMPAT is set for 32-bit syscall entries and then |
| * remains set until we return to user mode. |
| */ |
| - if (task_thread_info(task)->status & (TS_COMPAT|TS_I386_REGS_POKED)) |
| + if (task->thread.status & (TS_COMPAT|TS_I386_REGS_POKED)) |
| /* |
| * Sign-extend the value so (int)-EFOO becomes (long)-EFOO |
| * and will match correctly in comparisons. |
| @@ -116,7 +116,7 @@ static inline void syscall_get_arguments(struct task_struct *task, |
| unsigned long *args) |
| { |
| # ifdef CONFIG_IA32_EMULATION |
| - if (task_thread_info(task)->status & TS_COMPAT) |
| + if (task->thread.status & TS_COMPAT) |
| switch (i) { |
| case 0: |
| if (!n--) break; |
| @@ -177,7 +177,7 @@ static inline void syscall_set_arguments(struct task_struct *task, |
| const unsigned long *args) |
| { |
| # ifdef CONFIG_IA32_EMULATION |
| - if (task_thread_info(task)->status & TS_COMPAT) |
| + if (task->thread.status & TS_COMPAT) |
| switch (i) { |
| case 0: |
| if (!n--) break; |
| @@ -234,18 +234,8 @@ static inline void syscall_set_arguments(struct task_struct *task, |
| |
| static inline int syscall_get_arch(void) |
| { |
| -#ifdef CONFIG_IA32_EMULATION |
| - /* |
| - * TS_COMPAT is set for 32-bit syscall entry and then |
| - * remains set until we return to user mode. |
| - * |
| - * x32 tasks should be considered AUDIT_ARCH_X86_64. |
| - */ |
| - if (task_thread_info(current)->status & TS_COMPAT) |
| - return AUDIT_ARCH_I386; |
| -#endif |
| - /* Both x32 and x86_64 are considered "64-bit". */ |
| - return AUDIT_ARCH_X86_64; |
| + /* x32 tasks should be considered AUDIT_ARCH_X86_64. */ |
| + return in_ia32_syscall() ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64; |
| } |
| #endif /* CONFIG_X86_32 */ |
| |
| diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h |
| index 494c4b5ada34..c9dcfe7c7e4b 100644 |
| --- a/arch/x86/include/asm/thread_info.h |
| +++ b/arch/x86/include/asm/thread_info.h |
| @@ -55,7 +55,6 @@ struct task_struct; |
| struct thread_info { |
| struct task_struct *task; /* main task structure */ |
| __u32 flags; /* low level flags */ |
| - __u32 status; /* thread synchronous flags */ |
| __u32 cpu; /* current CPU */ |
| }; |
| |
| @@ -253,31 +252,17 @@ static inline int arch_within_stack_frames(const void * const stack, |
| |
| #endif |
| |
| -/* |
| - * Thread-synchronous status. |
| - * |
| - * This is different from the flags in that nobody else |
| - * ever touches our thread-synchronous status, so we don't |
| - * have to worry about atomic accesses. |
| - */ |
| -#define TS_COMPAT 0x0002 /* 32bit syscall active (64BIT)*/ |
| #ifdef CONFIG_COMPAT |
| #define TS_I386_REGS_POKED 0x0004 /* regs poked by 32-bit ptracer */ |
| #endif |
| - |
| #ifndef __ASSEMBLY__ |
| |
| -static inline bool in_ia32_syscall(void) |
| -{ |
| #ifdef CONFIG_X86_32 |
| - return true; |
| -#endif |
| -#ifdef CONFIG_IA32_EMULATION |
| - if (current_thread_info()->status & TS_COMPAT) |
| - return true; |
| +#define in_ia32_syscall() true |
| +#else |
| +#define in_ia32_syscall() (IS_ENABLED(CONFIG_IA32_EMULATION) && \ |
| + current->thread.status & TS_COMPAT) |
| #endif |
| - return false; |
| -} |
| |
| /* |
| * Force syscall return via IRET by making it look as if there was |
| diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c |
| index db3a0af9b9ec..add5f90b93d4 100644 |
| --- a/arch/x86/kernel/asm-offsets.c |
| +++ b/arch/x86/kernel/asm-offsets.c |
| @@ -36,7 +36,6 @@ void common(void) { |
| |
| BLANK(); |
| OFFSET(TI_flags, thread_info, flags); |
| - OFFSET(TI_status, thread_info, status); |
| |
| BLANK(); |
| OFFSET(TASK_addr_limit, task_struct, thread.addr_limit); |
| diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c |
| index 93982aebb398..2f2b8c7ccb85 100644 |
| --- a/arch/x86/kernel/fpu/init.c |
| +++ b/arch/x86/kernel/fpu/init.c |
| @@ -317,7 +317,6 @@ static void __init fpu__init_system_ctx_switch(void) |
| on_boot_cpu = 0; |
| |
| WARN_ON_FPU(current->thread.fpu.fpstate_active); |
| - current_thread_info()->status = 0; |
| |
| if (boot_cpu_has(X86_FEATURE_XSAVEOPT) && eagerfpu != DISABLE) |
| eagerfpu = ENABLE; |
| diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c |
| index b812cd0d7889..de9acaf2d371 100644 |
| --- a/arch/x86/kernel/process_64.c |
| +++ b/arch/x86/kernel/process_64.c |
| @@ -510,7 +510,7 @@ void set_personality_ia32(bool x32) |
| current->personality &= ~READ_IMPLIES_EXEC; |
| /* in_compat_syscall() uses the presence of the x32 |
| syscall bit flag to determine compat status */ |
| - current_thread_info()->status &= ~TS_COMPAT; |
| + current->thread.status &= ~TS_COMPAT; |
| } else { |
| set_thread_flag(TIF_IA32); |
| clear_thread_flag(TIF_X32); |
| @@ -518,7 +518,7 @@ void set_personality_ia32(bool x32) |
| current->mm->context.ia32_compat = TIF_IA32; |
| current->personality |= force_personality32; |
| /* Prepare the first "return" to user space */ |
| - current_thread_info()->status |= TS_COMPAT; |
| + current->thread.status |= TS_COMPAT; |
| } |
| } |
| EXPORT_SYMBOL_GPL(set_personality_ia32); |
| diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c |
| index 5b88a1b26fc7..ce94c38cf4d6 100644 |
| --- a/arch/x86/kernel/ptrace.c |
| +++ b/arch/x86/kernel/ptrace.c |
| @@ -934,7 +934,7 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 value) |
| */ |
| regs->orig_ax = value; |
| if (syscall_get_nr(child, regs) >= 0) |
| - task_thread_info(child)->status |= TS_I386_REGS_POKED; |
| + child->thread.status |= TS_I386_REGS_POKED; |
| break; |
| |
| case offsetof(struct user32, regs.eflags): |
| diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c |
| index 04cb3212db2d..da20ecb5397a 100644 |
| --- a/arch/x86/kernel/signal.c |
| +++ b/arch/x86/kernel/signal.c |
| @@ -783,7 +783,7 @@ static inline unsigned long get_nr_restart_syscall(const struct pt_regs *regs) |
| * than the tracee. |
| */ |
| #ifdef CONFIG_IA32_EMULATION |
| - if (current_thread_info()->status & (TS_COMPAT|TS_I386_REGS_POKED)) |
| + if (current->thread.status & (TS_COMPAT|TS_I386_REGS_POKED)) |
| return __NR_ia32_restart_syscall; |
| #endif |
| #ifdef CONFIG_X86_X32_ABI |
| -- |
| 2.15.0 |
| |