aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/include/asm
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2012-02-19 13:06:34 -0500
committerH. Peter Anvin <hpa@zytor.com>2012-02-20 15:52:05 -0500
commitd1a797f388d6d30fa502915d1b9937ed758b7137 (patch)
treeab16d4c32792dea0f0f841d7bce9f37ef962ad79 /arch/x86/include/asm
parentc5a373942bbc41698724fc948c74f959f73407e5 (diff)
x32: Handle process creation
Allow an x32 process to be started. Originally-by: H. J. Lu <hjl.tools@gmail.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Diffstat (limited to 'arch/x86/include/asm')
-rw-r--r--arch/x86/include/asm/compat.h26
-rw-r--r--arch/x86/include/asm/elf.h25
2 files changed, 45 insertions, 6 deletions
diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h
index 7938b84e4506..e7f68b49c01a 100644
--- a/arch/x86/include/asm/compat.h
+++ b/arch/x86/include/asm/compat.h
@@ -6,6 +6,7 @@
6 */ 6 */
7#include <linux/types.h> 7#include <linux/types.h>
8#include <linux/sched.h> 8#include <linux/sched.h>
9#include <asm/processor.h>
9#include <asm/user32.h> 10#include <asm/user32.h>
10#include <asm/unistd.h> 11#include <asm/unistd.h>
11 12
@@ -187,7 +188,20 @@ struct compat_shmid64_ds {
187/* 188/*
188 * The type of struct elf_prstatus.pr_reg in compatible core dumps. 189 * The type of struct elf_prstatus.pr_reg in compatible core dumps.
189 */ 190 */
191#ifdef CONFIG_X86_X32_ABI
192typedef struct user_regs_struct compat_elf_gregset_t;
193
194#define PR_REG_SIZE(S) (test_thread_flag(TIF_IA32) ? 68 : 216)
195#define PRSTATUS_SIZE(S) (test_thread_flag(TIF_IA32) ? 144 : 296)
196#define SET_PR_FPVALID(S,V) \
197 do { *(int *) (((void *) &((S)->pr_reg)) + PR_REG_SIZE(0)) = (V); } \
198 while (0)
199
200#define COMPAT_USE_64BIT_TIME \
201 (!!(task_pt_regs(current)->orig_ax & __X32_SYSCALL_BIT))
202#else
190typedef struct user_regs_struct32 compat_elf_gregset_t; 203typedef struct user_regs_struct32 compat_elf_gregset_t;
204#endif
191 205
192/* 206/*
193 * A pointer passed in from user mode. This should not 207 * A pointer passed in from user mode. This should not
@@ -209,8 +223,16 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)
209 223
210static inline void __user *arch_compat_alloc_user_space(long len) 224static inline void __user *arch_compat_alloc_user_space(long len)
211{ 225{
212 struct pt_regs *regs = task_pt_regs(current); 226 compat_uptr_t sp;
213 return (void __user *)regs->sp - len; 227
228 if (test_thread_flag(TIF_IA32)) {
229 sp = task_pt_regs(current)->sp;
230 } else {
231 /* -128 for the x32 ABI redzone */
232 sp = percpu_read(old_rsp) - 128;
233 }
234
235 return (void __user *)round_down(sp - len, 16);
214} 236}
215 237
216static inline bool is_compat_task(void) 238static inline bool is_compat_task(void)
diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h
index 410fa6a219f6..83aabea95dd7 100644
--- a/arch/x86/include/asm/elf.h
+++ b/arch/x86/include/asm/elf.h
@@ -156,7 +156,12 @@ do { \
156#define elf_check_arch(x) \ 156#define elf_check_arch(x) \
157 ((x)->e_machine == EM_X86_64) 157 ((x)->e_machine == EM_X86_64)
158 158
159#define compat_elf_check_arch(x) elf_check_arch_ia32(x) 159#define compat_elf_check_arch(x) \
160 (elf_check_arch_ia32(x) || (x)->e_machine == EM_X86_64)
161
162#if __USER32_DS != __USER_DS
163# error "The following code assumes __USER32_DS == __USER_DS"
164#endif
160 165
161static inline void elf_common_init(struct thread_struct *t, 166static inline void elf_common_init(struct thread_struct *t,
162 struct pt_regs *regs, const u16 ds) 167 struct pt_regs *regs, const u16 ds)
@@ -179,8 +184,9 @@ static inline void elf_common_init(struct thread_struct *t,
179void start_thread_ia32(struct pt_regs *regs, u32 new_ip, u32 new_sp); 184void start_thread_ia32(struct pt_regs *regs, u32 new_ip, u32 new_sp);
180#define compat_start_thread start_thread_ia32 185#define compat_start_thread start_thread_ia32
181 186
182void set_personality_ia32(void); 187void set_personality_ia32(bool);
183#define COMPAT_SET_PERSONALITY(ex) set_personality_ia32() 188#define COMPAT_SET_PERSONALITY(ex) \
189 set_personality_ia32((ex).e_machine == EM_X86_64)
184 190
185#define COMPAT_ELF_PLATFORM ("i686") 191#define COMPAT_ELF_PLATFORM ("i686")
186 192
@@ -296,9 +302,20 @@ do { \
296 (unsigned long)current->mm->context.vdso); \ 302 (unsigned long)current->mm->context.vdso); \
297} while (0) 303} while (0)
298 304
305#define ARCH_DLINFO_X32 \
306do { \
307 if (vdso_enabled) \
308 NEW_AUX_ENT(AT_SYSINFO_EHDR, \
309 (unsigned long)current->mm->context.vdso); \
310} while (0)
311
299#define AT_SYSINFO 32 312#define AT_SYSINFO 32
300 313
301#define COMPAT_ARCH_DLINFO ARCH_DLINFO_IA32(sysctl_vsyscall32) 314#define COMPAT_ARCH_DLINFO \
315if (test_thread_flag(TIF_X32)) \
316 ARCH_DLINFO_X32; \
317else \
318 ARCH_DLINFO_IA32(sysctl_vsyscall32)
302 319
303#define COMPAT_ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x1000000) 320#define COMPAT_ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x1000000)
304 321