Commit 4cffe21d authored by Thomas Gleixner's avatar Thomas Gleixner

Merge branch 'x86/entry' into core/entry

Prepare for the merging of the syscall_work series which conflicts with the
TIF bits overhaul in X86.
parents 78a56e04 c8d5ed67
...@@ -413,10 +413,10 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) ...@@ -413,10 +413,10 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
int compat_arch_setup_additional_pages(struct linux_binprm *bprm, int compat_arch_setup_additional_pages(struct linux_binprm *bprm,
int uses_interp) int uses_interp, bool x32)
{ {
#ifdef CONFIG_X86_X32_ABI #ifdef CONFIG_X86_X32_ABI
if (test_thread_flag(TIF_X32)) { if (x32) {
if (!vdso64_enabled) if (!vdso64_enabled)
return 0; return 0;
return map_vdso_randomized(&vdso_image_x32); return map_vdso_randomized(&vdso_image_x32);
......
...@@ -316,7 +316,7 @@ static struct vm_area_struct gate_vma __ro_after_init = { ...@@ -316,7 +316,7 @@ static struct vm_area_struct gate_vma __ro_after_init = {
struct vm_area_struct *get_gate_vma(struct mm_struct *mm) struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
{ {
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
if (!mm || mm->context.ia32_compat) if (!mm || !(mm->context.flags & MM_CONTEXT_HAS_VSYSCALL))
return NULL; return NULL;
#endif #endif
if (vsyscall_mode == NONE) if (vsyscall_mode == NONE)
......
...@@ -2602,7 +2602,7 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry_ctx *ent ...@@ -2602,7 +2602,7 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry_ctx *ent
struct stack_frame_ia32 frame; struct stack_frame_ia32 frame;
const struct stack_frame_ia32 __user *fp; const struct stack_frame_ia32 __user *fp;
if (!test_thread_flag(TIF_IA32)) if (user_64bit_mode(regs))
return 0; return 0;
cs_base = get_segment_base(regs->cs); cs_base = get_segment_base(regs->cs);
......
...@@ -1259,7 +1259,7 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs) ...@@ -1259,7 +1259,7 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs)
old_to = to; old_to = to;
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
is_64bit = kernel_ip(to) || !test_thread_flag(TIF_IA32); is_64bit = kernel_ip(to) || any_64bit_mode(regs);
#endif #endif
insn_init(&insn, kaddr, size, is_64bit); insn_init(&insn, kaddr, size, is_64bit);
insn_get_length(&insn); insn_get_length(&insn);
......
...@@ -1221,7 +1221,7 @@ static int branch_type(unsigned long from, unsigned long to, int abort) ...@@ -1221,7 +1221,7 @@ static int branch_type(unsigned long from, unsigned long to, int abort)
* on 64-bit systems running 32-bit apps * on 64-bit systems running 32-bit apps
*/ */
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
is64 = kernel_ip((unsigned long)addr) || !test_thread_flag(TIF_IA32); is64 = kernel_ip((unsigned long)addr) || any_64bit_mode(current_pt_regs());
#endif #endif
insn_init(&insn, addr, bytes_read, is64); insn_init(&insn, addr, bytes_read, is64);
insn_get_opcode(&insn); insn_get_opcode(&insn);
......
...@@ -177,14 +177,13 @@ typedef struct user_regs_struct compat_elf_gregset_t; ...@@ -177,14 +177,13 @@ typedef struct user_regs_struct compat_elf_gregset_t;
static inline void __user *arch_compat_alloc_user_space(long len) static inline void __user *arch_compat_alloc_user_space(long len)
{ {
compat_uptr_t sp; compat_uptr_t sp = task_pt_regs(current)->sp;
if (test_thread_flag(TIF_IA32)) { /*
sp = task_pt_regs(current)->sp; * -128 for the x32 ABI redzone. For IA32, it is not strictly
} else { * necessary, but not harmful.
/* -128 for the x32 ABI redzone */ */
sp = task_pt_regs(current)->sp - 128; sp -= 128;
}
return (void __user *)round_down(sp - len, 16); return (void __user *)round_down(sp - len, 16);
} }
......
...@@ -186,8 +186,9 @@ static inline void elf_common_init(struct thread_struct *t, ...@@ -186,8 +186,9 @@ static inline void elf_common_init(struct thread_struct *t,
#define COMPAT_ELF_PLAT_INIT(regs, load_addr) \ #define COMPAT_ELF_PLAT_INIT(regs, load_addr) \
elf_common_init(&current->thread, regs, __USER_DS) elf_common_init(&current->thread, regs, __USER_DS)
void compat_start_thread(struct pt_regs *regs, u32 new_ip, u32 new_sp); void compat_start_thread(struct pt_regs *regs, u32 new_ip, u32 new_sp, bool x32);
#define compat_start_thread compat_start_thread #define COMPAT_START_THREAD(ex, regs, new_ip, new_sp) \
compat_start_thread(regs, new_ip, new_sp, ex->e_machine == EM_X86_64)
void set_personality_ia32(bool); void set_personality_ia32(bool);
#define COMPAT_SET_PERSONALITY(ex) \ #define COMPAT_SET_PERSONALITY(ex) \
...@@ -361,7 +362,7 @@ do { \ ...@@ -361,7 +362,7 @@ do { \
#define AT_SYSINFO 32 #define AT_SYSINFO 32
#define COMPAT_ARCH_DLINFO \ #define COMPAT_ARCH_DLINFO \
if (test_thread_flag(TIF_X32)) \ if (exec->e_machine == EM_X86_64) \
ARCH_DLINFO_X32; \ ARCH_DLINFO_X32; \
else \ else \
ARCH_DLINFO_IA32 ARCH_DLINFO_IA32
...@@ -382,8 +383,10 @@ struct linux_binprm; ...@@ -382,8 +383,10 @@ struct linux_binprm;
extern int arch_setup_additional_pages(struct linux_binprm *bprm, extern int arch_setup_additional_pages(struct linux_binprm *bprm,
int uses_interp); int uses_interp);
extern int compat_arch_setup_additional_pages(struct linux_binprm *bprm, extern int compat_arch_setup_additional_pages(struct linux_binprm *bprm,
int uses_interp); int uses_interp, bool x32);
#define compat_arch_setup_additional_pages compat_arch_setup_additional_pages #define COMPAT_ARCH_SETUP_ADDITIONAL_PAGES(bprm, ex, interpreter) \
compat_arch_setup_additional_pages(bprm, interpreter, \
(ex->e_machine == EM_X86_64))
/* Do not change the values. See get_align_mask() */ /* Do not change the values. See get_align_mask() */
enum align_flags { enum align_flags {
......
...@@ -6,6 +6,12 @@ ...@@ -6,6 +6,12 @@
#include <linux/rwsem.h> #include <linux/rwsem.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/atomic.h> #include <linux/atomic.h>
#include <linux/bits.h>
/* Uprobes on this MM assume 32-bit code */
#define MM_CONTEXT_UPROBE_IA32 BIT(0)
/* vsyscall page is accessible on this MM */
#define MM_CONTEXT_HAS_VSYSCALL BIT(1)
/* /*
* x86 has arch-specific MMU state beyond what lives in mm_struct. * x86 has arch-specific MMU state beyond what lives in mm_struct.
...@@ -33,8 +39,7 @@ typedef struct { ...@@ -33,8 +39,7 @@ typedef struct {
#endif #endif
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
/* True if mm supports a task running in 32 bit compatibility mode. */ unsigned short flags;
unsigned short ia32_compat;
#endif #endif
struct mutex lock; struct mutex lock;
......
...@@ -177,7 +177,7 @@ static inline void arch_exit_mmap(struct mm_struct *mm) ...@@ -177,7 +177,7 @@ static inline void arch_exit_mmap(struct mm_struct *mm)
static inline bool is_64bit_mm(struct mm_struct *mm) static inline bool is_64bit_mm(struct mm_struct *mm)
{ {
return !IS_ENABLED(CONFIG_IA32_EMULATION) || return !IS_ENABLED(CONFIG_IA32_EMULATION) ||
!(mm->context.ia32_compat == TIF_IA32); !(mm->context.flags & MM_CONTEXT_UPROBE_IA32);
} }
#else #else
static inline bool is_64bit_mm(struct mm_struct *mm) static inline bool is_64bit_mm(struct mm_struct *mm)
......
...@@ -91,7 +91,7 @@ struct thread_info { ...@@ -91,7 +91,7 @@ struct thread_info {
#define TIF_NEED_FPU_LOAD 14 /* load FPU on return to userspace */ #define TIF_NEED_FPU_LOAD 14 /* load FPU on return to userspace */
#define TIF_NOCPUID 15 /* CPUID is not accessible in userland */ #define TIF_NOCPUID 15 /* CPUID is not accessible in userland */
#define TIF_NOTSC 16 /* TSC is not accessible in userland */ #define TIF_NOTSC 16 /* TSC is not accessible in userland */
#define TIF_IA32 17 /* IA32 compatibility process */ #define TIF_NOTIFY_SIGNAL 17 /* signal notifications exist */
#define TIF_SLD 18 /* Restore split lock detection on context switch */ #define TIF_SLD 18 /* Restore split lock detection on context switch */
#define TIF_MEMDIE 20 /* is terminating due to OOM killer */ #define TIF_MEMDIE 20 /* is terminating due to OOM killer */
#define TIF_POLLING_NRFLAG 21 /* idle is polling for TIF_NEED_RESCHED */ #define TIF_POLLING_NRFLAG 21 /* idle is polling for TIF_NEED_RESCHED */
...@@ -101,7 +101,6 @@ struct thread_info { ...@@ -101,7 +101,6 @@ struct thread_info {
#define TIF_LAZY_MMU_UPDATES 27 /* task is updating the mmu lazily */ #define TIF_LAZY_MMU_UPDATES 27 /* task is updating the mmu lazily */
#define TIF_SYSCALL_TRACEPOINT 28 /* syscall tracepoint instrumentation */ #define TIF_SYSCALL_TRACEPOINT 28 /* syscall tracepoint instrumentation */
#define TIF_ADDR32 29 /* 32-bit address space on 64 bits */ #define TIF_ADDR32 29 /* 32-bit address space on 64 bits */
#define TIF_X32 30 /* 32-bit native x86-64 binary */
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
...@@ -120,7 +119,7 @@ struct thread_info { ...@@ -120,7 +119,7 @@ struct thread_info {
#define _TIF_NEED_FPU_LOAD (1 << TIF_NEED_FPU_LOAD) #define _TIF_NEED_FPU_LOAD (1 << TIF_NEED_FPU_LOAD)
#define _TIF_NOCPUID (1 << TIF_NOCPUID) #define _TIF_NOCPUID (1 << TIF_NOCPUID)
#define _TIF_NOTSC (1 << TIF_NOTSC) #define _TIF_NOTSC (1 << TIF_NOTSC)
#define _TIF_IA32 (1 << TIF_IA32) #define _TIF_NOTIFY_SIGNAL (1 << TIF_NOTIFY_SIGNAL)
#define _TIF_SLD (1 << TIF_SLD) #define _TIF_SLD (1 << TIF_SLD)
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
#define _TIF_IO_BITMAP (1 << TIF_IO_BITMAP) #define _TIF_IO_BITMAP (1 << TIF_IO_BITMAP)
...@@ -129,7 +128,6 @@ struct thread_info { ...@@ -129,7 +128,6 @@ struct thread_info {
#define _TIF_LAZY_MMU_UPDATES (1 << TIF_LAZY_MMU_UPDATES) #define _TIF_LAZY_MMU_UPDATES (1 << TIF_LAZY_MMU_UPDATES)
#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT) #define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT)
#define _TIF_ADDR32 (1 << TIF_ADDR32) #define _TIF_ADDR32 (1 << TIF_ADDR32)
#define _TIF_X32 (1 << TIF_X32)
/* flags to check in __switch_to() */ /* flags to check in __switch_to() */
#define _TIF_WORK_CTXSW_BASE \ #define _TIF_WORK_CTXSW_BASE \
......
...@@ -123,7 +123,7 @@ int perf_reg_validate(u64 mask) ...@@ -123,7 +123,7 @@ int perf_reg_validate(u64 mask)
u64 perf_reg_abi(struct task_struct *task) u64 perf_reg_abi(struct task_struct *task)
{ {
if (test_tsk_thread_flag(task, TIF_IA32)) if (!user_64bit_mode(task_pt_regs(task)))
return PERF_SAMPLE_REGS_ABI_32; return PERF_SAMPLE_REGS_ABI_32;
else else
return PERF_SAMPLE_REGS_ABI_64; return PERF_SAMPLE_REGS_ABI_64;
......
...@@ -511,11 +511,10 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp) ...@@ -511,11 +511,10 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
EXPORT_SYMBOL_GPL(start_thread); EXPORT_SYMBOL_GPL(start_thread);
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
void compat_start_thread(struct pt_regs *regs, u32 new_ip, u32 new_sp) void compat_start_thread(struct pt_regs *regs, u32 new_ip, u32 new_sp, bool x32)
{ {
start_thread_common(regs, new_ip, new_sp, start_thread_common(regs, new_ip, new_sp,
test_thread_flag(TIF_X32) x32 ? __USER_CS : __USER32_CS,
? __USER_CS : __USER32_CS,
__USER_DS, __USER_DS); __USER_DS, __USER_DS);
} }
#endif #endif
...@@ -641,16 +640,12 @@ void set_personality_64bit(void) ...@@ -641,16 +640,12 @@ void set_personality_64bit(void)
/* inherit personality from parent */ /* inherit personality from parent */
/* Make sure to be in 64bit mode */ /* Make sure to be in 64bit mode */
clear_thread_flag(TIF_IA32);
clear_thread_flag(TIF_ADDR32); clear_thread_flag(TIF_ADDR32);
clear_thread_flag(TIF_X32);
/* Pretend that this comes from a 64bit execve */ /* Pretend that this comes from a 64bit execve */
task_pt_regs(current)->orig_ax = __NR_execve; task_pt_regs(current)->orig_ax = __NR_execve;
current_thread_info()->status &= ~TS_COMPAT; current_thread_info()->status &= ~TS_COMPAT;
/* Ensure the corresponding mm is not marked. */
if (current->mm) if (current->mm)
current->mm->context.ia32_compat = 0; current->mm->context.flags = MM_CONTEXT_HAS_VSYSCALL;
/* TBD: overwrites user setup. Should have two bits. /* TBD: overwrites user setup. Should have two bits.
But 64bit processes have always behaved this way, But 64bit processes have always behaved this way,
...@@ -662,10 +657,9 @@ void set_personality_64bit(void) ...@@ -662,10 +657,9 @@ void set_personality_64bit(void)
static void __set_personality_x32(void) static void __set_personality_x32(void)
{ {
#ifdef CONFIG_X86_X32 #ifdef CONFIG_X86_X32
clear_thread_flag(TIF_IA32);
set_thread_flag(TIF_X32);
if (current->mm) if (current->mm)
current->mm->context.ia32_compat = TIF_X32; current->mm->context.flags = 0;
current->personality &= ~READ_IMPLIES_EXEC; current->personality &= ~READ_IMPLIES_EXEC;
/* /*
* in_32bit_syscall() uses the presence of the x32 syscall bit * in_32bit_syscall() uses the presence of the x32 syscall bit
...@@ -683,10 +677,14 @@ static void __set_personality_x32(void) ...@@ -683,10 +677,14 @@ static void __set_personality_x32(void)
static void __set_personality_ia32(void) static void __set_personality_ia32(void)
{ {
#ifdef CONFIG_IA32_EMULATION #ifdef CONFIG_IA32_EMULATION
set_thread_flag(TIF_IA32); if (current->mm) {
clear_thread_flag(TIF_X32); /*
if (current->mm) * uprobes applied to this MM need to know this and
current->mm->context.ia32_compat = TIF_IA32; * cannot use user_64bit_mode() at that time.
*/
current->mm->context.flags = MM_CONTEXT_UPROBE_IA32;
}
current->personality |= force_personality32; current->personality |= force_personality32;
/* Prepare the first "return" to user space */ /* Prepare the first "return" to user space */
task_pt_regs(current)->orig_ax = __NR_ia32_execve; task_pt_regs(current)->orig_ax = __NR_ia32_execve;
......
...@@ -49,7 +49,7 @@ x86_backtrace_32(struct pt_regs * const regs, unsigned int depth) ...@@ -49,7 +49,7 @@ x86_backtrace_32(struct pt_regs * const regs, unsigned int depth)
struct stack_frame_ia32 *head; struct stack_frame_ia32 *head;
/* User process is IA32 */ /* User process is IA32 */
if (!current || !test_thread_flag(TIF_IA32)) if (!current || user_64bit_mode(regs))
return 0; return 0;
head = (struct stack_frame_ia32 *) regs->bp; head = (struct stack_frame_ia32 *) regs->bp;
......
...@@ -1246,7 +1246,7 @@ static int load_elf_binary(struct linux_binprm *bprm) ...@@ -1246,7 +1246,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
set_binfmt(&elf_format); set_binfmt(&elf_format);
#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES #ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
retval = arch_setup_additional_pages(bprm, !!interpreter); retval = ARCH_SETUP_ADDITIONAL_PAGES(bprm, elf_ex, !!interpreter);
if (retval < 0) if (retval < 0)
goto out; goto out;
#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */ #endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */
...@@ -1307,7 +1307,7 @@ static int load_elf_binary(struct linux_binprm *bprm) ...@@ -1307,7 +1307,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
#endif #endif
finalize_exec(bprm); finalize_exec(bprm);
start_thread(regs, elf_entry, bprm->p); START_THREAD(elf_ex, regs, elf_entry, bprm->p);
retval = 0; retval = 0;
out: out:
return retval; return retval;
......
...@@ -106,15 +106,25 @@ ...@@ -106,15 +106,25 @@
#endif #endif
#ifdef compat_start_thread #ifdef compat_start_thread
#undef start_thread #define COMPAT_START_THREAD(ex, regs, new_ip, new_sp) \
#define start_thread compat_start_thread compat_start_thread(regs, new_ip, new_sp)
#endif
#ifdef COMPAT_START_THREAD
#undef START_THREAD
#define START_THREAD COMPAT_START_THREAD
#endif #endif
#ifdef compat_arch_setup_additional_pages #ifdef compat_arch_setup_additional_pages
#define COMPAT_ARCH_SETUP_ADDITIONAL_PAGES(bprm, ex, interpreter) \
compat_arch_setup_additional_pages(bprm, interpreter)
#endif
#ifdef COMPAT_ARCH_SETUP_ADDITIONAL_PAGES
#undef ARCH_HAS_SETUP_ADDITIONAL_PAGES #undef ARCH_HAS_SETUP_ADDITIONAL_PAGES
#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1 #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
#undef arch_setup_additional_pages #undef ARCH_SETUP_ADDITIONAL_PAGES
#define arch_setup_additional_pages compat_arch_setup_additional_pages #define ARCH_SETUP_ADDITIONAL_PAGES COMPAT_ARCH_SETUP_ADDITIONAL_PAGES
#endif #endif
#ifdef compat_elf_read_implies_exec #ifdef compat_elf_read_implies_exec
......
...@@ -22,6 +22,16 @@ ...@@ -22,6 +22,16 @@
SET_PERSONALITY(ex) SET_PERSONALITY(ex)
#endif #endif
#ifndef START_THREAD
#define START_THREAD(elf_ex, regs, elf_entry, start_stack) \
start_thread(regs, elf_entry, start_stack)
#endif
#if defined(ARCH_HAS_SETUP_ADDITIONAL_PAGES) && !defined(ARCH_SETUP_ADDITIONAL_PAGES)
#define ARCH_SETUP_ADDITIONAL_PAGES(bprm, ex, interpreter) \
arch_setup_additional_pages(bprm, interpreter)
#endif
#define ELF32_GNU_PROPERTY_ALIGN 4 #define ELF32_GNU_PROPERTY_ALIGN 4
#define ELF64_GNU_PROPERTY_ALIGN 8 #define ELF64_GNU_PROPERTY_ALIGN 8
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment