diff options
-rw-r--r-- | arch/x86/include/asm/compat.h | 13 | ||||
-rw-r--r-- | arch/x86/include/asm/syscall.h | 5 | ||||
-rw-r--r-- | arch/x86/include/asm/unistd.h | 7 | ||||
-rw-r--r-- | arch/x86/kernel/entry_64.S | 10 |
4 files changed, 31 insertions, 4 deletions
diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h index 30d737ef2a42..7938b84e4506 100644 --- a/arch/x86/include/asm/compat.h +++ b/arch/x86/include/asm/compat.h | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <linux/types.h> | 7 | #include <linux/types.h> |
8 | #include <linux/sched.h> | 8 | #include <linux/sched.h> |
9 | #include <asm/user32.h> | 9 | #include <asm/user32.h> |
10 | #include <asm/unistd.h> | ||
10 | 11 | ||
11 | #define COMPAT_USER_HZ 100 | 12 | #define COMPAT_USER_HZ 100 |
12 | #define COMPAT_UTS_MACHINE "i686\0\0" | 13 | #define COMPAT_UTS_MACHINE "i686\0\0" |
@@ -212,9 +213,17 @@ static inline void __user *arch_compat_alloc_user_space(long len) | |||
212 | return (void __user *)regs->sp - len; | 213 | return (void __user *)regs->sp - len; |
213 | } | 214 | } |
214 | 215 | ||
215 | static inline int is_compat_task(void) | 216 | static inline bool is_compat_task(void) |
216 | { | 217 | { |
217 | return current_thread_info()->status & TS_COMPAT; | 218 | #ifdef CONFIG_IA32_EMULATION |
219 | if (current_thread_info()->status & TS_COMPAT) | ||
220 | return true; | ||
221 | #endif | ||
222 | #ifdef CONFIG_X86_X32_ABI | ||
223 | if (task_pt_regs(current)->orig_ax & __X32_SYSCALL_BIT) | ||
224 | return true; | ||
225 | #endif | ||
226 | return false; | ||
218 | } | 227 | } |
219 | 228 | ||
220 | #endif /* _ASM_X86_COMPAT_H */ | 229 | #endif /* _ASM_X86_COMPAT_H */ |
diff --git a/arch/x86/include/asm/syscall.h b/arch/x86/include/asm/syscall.h index d962e5652a73..386b78686c4d 100644 --- a/arch/x86/include/asm/syscall.h +++ b/arch/x86/include/asm/syscall.h | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/sched.h> | 16 | #include <linux/sched.h> |
17 | #include <linux/err.h> | 17 | #include <linux/err.h> |
18 | #include <asm/asm-offsets.h> /* For NR_syscalls */ | 18 | #include <asm/asm-offsets.h> /* For NR_syscalls */ |
19 | #include <asm/unistd.h> | ||
19 | 20 | ||
20 | extern const unsigned long sys_call_table[]; | 21 | extern const unsigned long sys_call_table[]; |
21 | 22 | ||
@@ -26,13 +27,13 @@ extern const unsigned long sys_call_table[]; | |||
26 | */ | 27 | */ |
27 | static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs) | 28 | static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs) |
28 | { | 29 | { |
29 | return regs->orig_ax; | 30 | return regs->orig_ax & __SYSCALL_MASK; |
30 | } | 31 | } |
31 | 32 | ||
32 | static inline void syscall_rollback(struct task_struct *task, | 33 | static inline void syscall_rollback(struct task_struct *task, |
33 | struct pt_regs *regs) | 34 | struct pt_regs *regs) |
34 | { | 35 | { |
35 | regs->ax = regs->orig_ax; | 36 | regs->ax = regs->orig_ax & __SYSCALL_MASK; |
36 | } | 37 | } |
37 | 38 | ||
38 | static inline long syscall_get_error(struct task_struct *task, | 39 | static inline long syscall_get_error(struct task_struct *task, |
diff --git a/arch/x86/include/asm/unistd.h b/arch/x86/include/asm/unistd.h index 7a48a5557470..37cdc9d99bb1 100644 --- a/arch/x86/include/asm/unistd.h +++ b/arch/x86/include/asm/unistd.h | |||
@@ -5,6 +5,13 @@ | |||
5 | #define __X32_SYSCALL_BIT 0x40000000 | 5 | #define __X32_SYSCALL_BIT 0x40000000 |
6 | 6 | ||
7 | #ifdef __KERNEL__ | 7 | #ifdef __KERNEL__ |
8 | |||
9 | # ifdef CONFIG_X86_X32_ABI | ||
10 | # define __SYSCALL_MASK (~(__X32_SYSCALL_BIT)) | ||
11 | # else | ||
12 | # define __SYSCALL_MASK (~0) | ||
13 | # endif | ||
14 | |||
8 | # ifdef CONFIG_X86_32 | 15 | # ifdef CONFIG_X86_32 |
9 | 16 | ||
10 | # include <asm/unistd_32.h> | 17 | # include <asm/unistd_32.h> |
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 3fe8239fd8fb..a17b34216971 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
@@ -482,7 +482,12 @@ GLOBAL(system_call_after_swapgs) | |||
482 | testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) | 482 | testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) |
483 | jnz tracesys | 483 | jnz tracesys |
484 | system_call_fastpath: | 484 | system_call_fastpath: |
485 | #if __SYSCALL_MASK == ~0 | ||
485 | cmpq $__NR_syscall_max,%rax | 486 | cmpq $__NR_syscall_max,%rax |
487 | #else | ||
488 | andl $__SYSCALL_MASK,%eax | ||
489 | cmpl $__NR_syscall_max,%eax | ||
490 | #endif | ||
486 | ja badsys | 491 | ja badsys |
487 | movq %r10,%rcx | 492 | movq %r10,%rcx |
488 | call *sys_call_table(,%rax,8) # XXX: rip relative | 493 | call *sys_call_table(,%rax,8) # XXX: rip relative |
@@ -596,7 +601,12 @@ tracesys: | |||
596 | */ | 601 | */ |
597 | LOAD_ARGS ARGOFFSET, 1 | 602 | LOAD_ARGS ARGOFFSET, 1 |
598 | RESTORE_REST | 603 | RESTORE_REST |
604 | #if __SYSCALL_MASK == ~0 | ||
599 | cmpq $__NR_syscall_max,%rax | 605 | cmpq $__NR_syscall_max,%rax |
606 | #else | ||
607 | andl $__SYSCALL_MASK,%eax | ||
608 | cmpl $__NR_syscall_max,%eax | ||
609 | #endif | ||
600 | ja int_ret_from_sys_call /* RAX(%rsp) set to -ENOSYS above */ | 610 | ja int_ret_from_sys_call /* RAX(%rsp) set to -ENOSYS above */ |
601 | movq %r10,%rcx /* fixup for C */ | 611 | movq %r10,%rcx /* fixup for C */ |
602 | call *sys_call_table(,%rax,8) | 612 | call *sys_call_table(,%rax,8) |