diff options
Diffstat (limited to 'arch/x86/include/asm/elf.h')
| -rw-r--r-- | arch/x86/include/asm/elf.h | 88 | 
1 files changed, 68 insertions, 20 deletions
diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h index f2ad2163109..1a055c81d86 100644 --- a/arch/x86/include/asm/elf.h +++ b/arch/x86/include/asm/elf.h @@ -4,6 +4,7 @@  /*   * ELF register definitions..   */ +#include <linux/thread_info.h>  #include <asm/ptrace.h>  #include <asm/user.h> @@ -74,7 +75,12 @@ typedef struct user_fxsr_struct elf_fpxregset_t;  #include <asm/vdso.h> -extern unsigned int vdso_enabled; +#ifdef CONFIG_X86_64 +extern unsigned int vdso64_enabled; +#endif +#if defined(CONFIG_X86_32) || defined(CONFIG_COMPAT) +extern unsigned int vdso32_enabled; +#endif  /*   * This is used to ensure we don't load something for the wrong architecture. @@ -83,7 +89,6 @@ extern unsigned int vdso_enabled;  	(((x)->e_machine == EM_386) || ((x)->e_machine == EM_486))  #include <asm/processor.h> -#include <asm/system.h>  #ifdef CONFIG_X86_32  #include <asm/desc.h> @@ -155,7 +160,12 @@ do {						\  #define elf_check_arch(x)			\  	((x)->e_machine == EM_X86_64) -#define compat_elf_check_arch(x)	elf_check_arch_ia32(x) +#define compat_elf_check_arch(x)		\ +	(elf_check_arch_ia32(x) || (x)->e_machine == EM_X86_64) + +#if __USER32_DS != __USER_DS +# error "The following code assumes __USER32_DS == __USER_DS" +#endif  static inline void elf_common_init(struct thread_struct *t,  				   struct pt_regs *regs, const u16 ds) @@ -178,8 +188,9 @@ static inline void elf_common_init(struct thread_struct *t,  void start_thread_ia32(struct pt_regs *regs, u32 new_ip, u32 new_sp);  #define compat_start_thread start_thread_ia32 -void set_personality_ia32(void); -#define COMPAT_SET_PERSONALITY(ex) set_personality_ia32() +void set_personality_ia32(bool); +#define COMPAT_SET_PERSONALITY(ex)			\ +	set_personality_ia32((ex).e_machine == EM_X86_64)  #define COMPAT_ELF_PLATFORM			("i686") @@ -263,9 +274,9 @@ extern int force_personality32;  struct task_struct; -#define	ARCH_DLINFO_IA32(vdso_enabled)					\ +#define	ARCH_DLINFO_IA32						\  do {									\ -	if (vdso_enabled) {						\ +	if (vdso32_enabled) {						\  		NEW_AUX_ENT(AT_SYSINFO,	VDSO_ENTRY);			\  		NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_CURRENT_BASE);	\  	}								\ @@ -275,29 +286,37 @@ do {									\  #define STACK_RND_MASK (0x7ff) -#define VDSO_HIGH_BASE		(__fix_to_virt(FIX_VDSO)) - -#define ARCH_DLINFO		ARCH_DLINFO_IA32(vdso_enabled) +#define ARCH_DLINFO		ARCH_DLINFO_IA32  /* update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT entries changes */  #else /* CONFIG_X86_32 */ -#define VDSO_HIGH_BASE		0xffffe000U /* CONFIG_COMPAT_VDSO address */ -  /* 1GB for 64bit, 8MB for 32bit */ -#define STACK_RND_MASK (test_thread_flag(TIF_IA32) ? 0x7ff : 0x3fffff) +#define STACK_RND_MASK (test_thread_flag(TIF_ADDR32) ? 0x7ff : 0x3fffff)  #define ARCH_DLINFO							\  do {									\ -	if (vdso_enabled)						\ +	if (vdso64_enabled)						\  		NEW_AUX_ENT(AT_SYSINFO_EHDR,				\ -			    (unsigned long)current->mm->context.vdso);	\ +			    (unsigned long __force)current->mm->context.vdso); \ +} while (0) + +/* As a historical oddity, the x32 and x86_64 vDSOs are controlled together. */ +#define ARCH_DLINFO_X32							\ +do {									\ +	if (vdso64_enabled)						\ +		NEW_AUX_ENT(AT_SYSINFO_EHDR,				\ +			    (unsigned long __force)current->mm->context.vdso); \  } while (0)  #define AT_SYSINFO		32 -#define COMPAT_ARCH_DLINFO	ARCH_DLINFO_IA32(sysctl_vsyscall32) +#define COMPAT_ARCH_DLINFO						\ +if (test_thread_flag(TIF_X32))						\ +	ARCH_DLINFO_X32;						\ +else									\ +	ARCH_DLINFO_IA32  #define COMPAT_ELF_ET_DYN_BASE	(TASK_UNMAPPED_BASE + 0x1000000) @@ -306,18 +325,47 @@ do {									\  #define VDSO_CURRENT_BASE	((unsigned long)current->mm->context.vdso)  #define VDSO_ENTRY							\ -	((unsigned long)VDSO32_SYMBOL(VDSO_CURRENT_BASE, vsyscall)) +	((unsigned long)current->mm->context.vdso +			\ +	 selected_vdso32->sym___kernel_vsyscall)  struct linux_binprm;  #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1  extern int arch_setup_additional_pages(struct linux_binprm *bprm,  				       int uses_interp); - -extern int syscall32_setup_pages(struct linux_binprm *, int exstack); -#define compat_arch_setup_additional_pages	syscall32_setup_pages +extern int compat_arch_setup_additional_pages(struct linux_binprm *bprm, +					      int uses_interp); +#define compat_arch_setup_additional_pages compat_arch_setup_additional_pages  extern unsigned long arch_randomize_brk(struct mm_struct *mm);  #define arch_randomize_brk arch_randomize_brk +/* + * True on X86_32 or when emulating IA32 on X86_64 + */ +static inline int mmap_is_ia32(void) +{ +#ifdef CONFIG_X86_32 +	return 1; +#endif +#ifdef CONFIG_IA32_EMULATION +	if (test_thread_flag(TIF_ADDR32)) +		return 1; +#endif +	return 0; +} + +/* Do not change the values. See get_align_mask() */ +enum align_flags { +	ALIGN_VA_32	= BIT(0), +	ALIGN_VA_64	= BIT(1), +}; + +struct va_alignment { +	int flags; +	unsigned long mask; +} ____cacheline_aligned; + +extern struct va_alignment va_align; +extern unsigned long align_vdso_addr(unsigned long);  #endif /* _ASM_X86_ELF_H */  | 
