diff options
author | H. Peter Anvin <hpa@zytor.com> | 2012-02-19 13:06:34 -0500 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2012-02-20 15:52:05 -0500 |
commit | d1a797f388d6d30fa502915d1b9937ed758b7137 (patch) | |
tree | ab16d4c32792dea0f0f841d7bce9f37ef962ad79 /arch/x86/kernel | |
parent | c5a373942bbc41698724fc948c74f959f73407e5 (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.c | 4 | ||||
-rw-r--r-- | arch/x86/kernel/entry_64.S | 15 | ||||
-rw-r--r-- | arch/x86/kernel/process_64.c | 23 |
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 | |||
1598 | static inline int | 1600 | static inline int |
1599 | perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry) | 1601 | perf_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 |
764 | END(stub_x32_rt_sigreturn) | 764 | END(stub_x32_rt_sigreturn) |
765 | 765 | ||
766 | ENTRY(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 | ||
779 | END(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) | |||
364 | void start_thread_ia32(struct pt_regs *regs, u32 new_ip, u32 new_sp) | 364 | void 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 | ||
525 | void set_personality_ia32(void) | 528 | void 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 | ||
543 | unsigned long get_wchan(struct task_struct *p) | 552 | unsigned long get_wchan(struct task_struct *p) |