aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel
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/kernel
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/kernel')
-rw-r--r--arch/x86/kernel/cpu/perf_event.c4
-rw-r--r--arch/x86/kernel/entry_64.S15
-rw-r--r--arch/x86/kernel/process_64.c23
3 files changed, 34 insertions, 8 deletions
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 5adce1040b1..63c0e058a40 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -28,7 +28,6 @@
28#include <asm/apic.h> 28#include <asm/apic.h>
29#include <asm/stacktrace.h> 29#include <asm/stacktrace.h>
30#include <asm/nmi.h> 30#include <asm/nmi.h>
31#include <asm/compat.h>
32#include <asm/smp.h> 31#include <asm/smp.h>
33#include <asm/alternative.h> 32#include <asm/alternative.h>
34 33
@@ -1595,6 +1594,9 @@ perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
1595} 1594}
1596 1595
1597#ifdef CONFIG_COMPAT 1596#ifdef CONFIG_COMPAT
1597
1598#include <asm/compat.h>
1599
1598static inline int 1600static inline int
1599perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry) 1601perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry)
1600{ 1602{
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 53dc821f0a6..9e036f0ce5e 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -763,6 +763,21 @@ ENTRY(stub_x32_rt_sigreturn)
763 CFI_ENDPROC 763 CFI_ENDPROC
764END(stub_x32_rt_sigreturn) 764END(stub_x32_rt_sigreturn)
765 765
766ENTRY(stub_x32_execve)
767 CFI_STARTPROC
768 addq $8, %rsp
769 PARTIAL_FRAME 0
770 SAVE_REST
771 FIXUP_TOP_OF_STACK %r11
772 movq %rsp, %rcx
773 call sys32_execve
774 RESTORE_TOP_OF_STACK %r11
775 movq %rax,RAX(%rsp)
776 RESTORE_REST
777 jmp int_ret_from_sys_call
778 CFI_ENDPROC
779END(stub_x32_execve)
780
766#endif 781#endif
767 782
768/* 783/*
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 5fe2fbaa56b..a0701da2bd1 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -364,7 +364,9 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
364void start_thread_ia32(struct pt_regs *regs, u32 new_ip, u32 new_sp) 364void start_thread_ia32(struct pt_regs *regs, u32 new_ip, u32 new_sp)
365{ 365{
366 start_thread_common(regs, new_ip, new_sp, 366 start_thread_common(regs, new_ip, new_sp,
367 __USER32_CS, __USER32_DS, __USER32_DS); 367 test_thread_flag(TIF_X32)
368 ? __USER_CS : __USER32_CS,
369 __USER_DS, __USER_DS);
368} 370}
369#endif 371#endif
370 372
@@ -508,6 +510,7 @@ void set_personality_64bit(void)
508 510
509 /* Make sure to be in 64bit mode */ 511 /* Make sure to be in 64bit mode */
510 clear_thread_flag(TIF_IA32); 512 clear_thread_flag(TIF_IA32);
513 clear_thread_flag(TIF_X32);
511 clear_thread_flag(TIF_ADDR32); 514 clear_thread_flag(TIF_ADDR32);
512 clear_thread_flag(TIF_X32); 515 clear_thread_flag(TIF_X32);
513 516
@@ -522,22 +525,28 @@ void set_personality_64bit(void)
522 current->personality &= ~READ_IMPLIES_EXEC; 525 current->personality &= ~READ_IMPLIES_EXEC;
523} 526}
524 527
525void set_personality_ia32(void) 528void set_personality_ia32(bool x32)
526{ 529{
527 /* inherit personality from parent */ 530 /* inherit personality from parent */
528 531
529 /* Make sure to be in 32bit mode */ 532 /* Make sure to be in 32bit mode */
530 set_thread_flag(TIF_IA32);
531 set_thread_flag(TIF_ADDR32); 533 set_thread_flag(TIF_ADDR32);
532 clear_thread_flag(TIF_X32);
533 current->personality |= force_personality32;
534 534
535 /* Mark the associated mm as containing 32-bit tasks. */ 535 /* Mark the associated mm as containing 32-bit tasks. */
536 if (current->mm) 536 if (current->mm)
537 current->mm->context.ia32_compat = 1; 537 current->mm->context.ia32_compat = 1;
538 538
539 /* Prepare the first "return" to user space */ 539 if (x32) {
540 current_thread_info()->status |= TS_COMPAT; 540 clear_thread_flag(TIF_IA32);
541 set_thread_flag(TIF_X32);
542 current->personality &= ~READ_IMPLIES_EXEC;
543 } else {
544 set_thread_flag(TIF_IA32);
545 clear_thread_flag(TIF_X32);
546 current->personality |= force_personality32;
547 /* Prepare the first "return" to user space */
548 current_thread_info()->status |= TS_COMPAT;
549 }
541} 550}
542 551
543unsigned long get_wchan(struct task_struct *p) 552unsigned long get_wchan(struct task_struct *p)