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>
This commit is contained in:
H. Peter Anvin
2012-02-19 10:06:34 -08:00
parent c5a373942b
commit d1a797f388
5 changed files with 79 additions and 14 deletions

View File

@@ -28,7 +28,6 @@
#include <asm/apic.h>
#include <asm/stacktrace.h>
#include <asm/nmi.h>
#include <asm/compat.h>
#include <asm/smp.h>
#include <asm/alternative.h>
@@ -1595,6 +1594,9 @@ perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
}
#ifdef CONFIG_COMPAT
#include <asm/compat.h>
static inline int
perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry)
{

View File

@@ -763,6 +763,21 @@ ENTRY(stub_x32_rt_sigreturn)
CFI_ENDPROC
END(stub_x32_rt_sigreturn)
ENTRY(stub_x32_execve)
CFI_STARTPROC
addq $8, %rsp
PARTIAL_FRAME 0
SAVE_REST
FIXUP_TOP_OF_STACK %r11
movq %rsp, %rcx
call sys32_execve
RESTORE_TOP_OF_STACK %r11
movq %rax,RAX(%rsp)
RESTORE_REST
jmp int_ret_from_sys_call
CFI_ENDPROC
END(stub_x32_execve)
#endif
/*

View File

@@ -364,7 +364,9 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
void start_thread_ia32(struct pt_regs *regs, u32 new_ip, u32 new_sp)
{
start_thread_common(regs, new_ip, new_sp,
__USER32_CS, __USER32_DS, __USER32_DS);
test_thread_flag(TIF_X32)
? __USER_CS : __USER32_CS,
__USER_DS, __USER_DS);
}
#endif
@@ -508,6 +510,7 @@ void set_personality_64bit(void)
/* Make sure to be in 64bit mode */
clear_thread_flag(TIF_IA32);
clear_thread_flag(TIF_X32);
clear_thread_flag(TIF_ADDR32);
clear_thread_flag(TIF_X32);
@@ -522,22 +525,28 @@ void set_personality_64bit(void)
current->personality &= ~READ_IMPLIES_EXEC;
}
void set_personality_ia32(void)
void set_personality_ia32(bool x32)
{
/* inherit personality from parent */
/* Make sure to be in 32bit mode */
set_thread_flag(TIF_IA32);
set_thread_flag(TIF_ADDR32);
clear_thread_flag(TIF_X32);
current->personality |= force_personality32;
/* Mark the associated mm as containing 32-bit tasks. */
if (current->mm)
current->mm->context.ia32_compat = 1;
/* Prepare the first "return" to user space */
current_thread_info()->status |= TS_COMPAT;
if (x32) {
clear_thread_flag(TIF_IA32);
set_thread_flag(TIF_X32);
current->personality &= ~READ_IMPLIES_EXEC;
} else {
set_thread_flag(TIF_IA32);
clear_thread_flag(TIF_X32);
current->personality |= force_personality32;
/* Prepare the first "return" to user space */
current_thread_info()->status |= TS_COMPAT;
}
}
unsigned long get_wchan(struct task_struct *p)