diff options
Diffstat (limited to 'arch/mips/include/asm/syscall.h')
-rw-r--r-- | arch/mips/include/asm/syscall.h | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/arch/mips/include/asm/syscall.h b/arch/mips/include/asm/syscall.h index fc556d8052c9..c6e9cd2bca8d 100644 --- a/arch/mips/include/asm/syscall.h +++ b/arch/mips/include/asm/syscall.h | |||
@@ -13,23 +13,35 @@ | |||
13 | #ifndef __ASM_MIPS_SYSCALL_H | 13 | #ifndef __ASM_MIPS_SYSCALL_H |
14 | #define __ASM_MIPS_SYSCALL_H | 14 | #define __ASM_MIPS_SYSCALL_H |
15 | 15 | ||
16 | #include <linux/compiler.h> | ||
16 | #include <uapi/linux/audit.h> | 17 | #include <uapi/linux/audit.h> |
17 | #include <linux/elf-em.h> | 18 | #include <linux/elf-em.h> |
18 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
19 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
20 | #include <linux/uaccess.h> | 21 | #include <linux/uaccess.h> |
21 | #include <asm/ptrace.h> | 22 | #include <asm/ptrace.h> |
23 | #include <asm/unistd.h> | ||
24 | |||
25 | #ifndef __NR_syscall /* Only defined if _MIPS_SIM == _MIPS_SIM_ABI32 */ | ||
26 | #define __NR_syscall 4000 | ||
27 | #endif | ||
22 | 28 | ||
23 | static inline long syscall_get_nr(struct task_struct *task, | 29 | static inline long syscall_get_nr(struct task_struct *task, |
24 | struct pt_regs *regs) | 30 | struct pt_regs *regs) |
25 | { | 31 | { |
26 | return regs->regs[2]; | 32 | /* O32 ABI syscall() - Either 64-bit with O32 or 32-bit */ |
33 | if ((config_enabled(CONFIG_32BIT) || | ||
34 | test_tsk_thread_flag(task, TIF_32BIT_REGS)) && | ||
35 | (regs->regs[2] == __NR_syscall)) | ||
36 | return regs->regs[4]; | ||
37 | else | ||
38 | return regs->regs[2]; | ||
27 | } | 39 | } |
28 | 40 | ||
29 | static inline unsigned long mips_get_syscall_arg(unsigned long *arg, | 41 | static inline unsigned long mips_get_syscall_arg(unsigned long *arg, |
30 | struct task_struct *task, struct pt_regs *regs, unsigned int n) | 42 | struct task_struct *task, struct pt_regs *regs, unsigned int n) |
31 | { | 43 | { |
32 | unsigned long usp = regs->regs[29]; | 44 | unsigned long usp __maybe_unused = regs->regs[29]; |
33 | 45 | ||
34 | switch (n) { | 46 | switch (n) { |
35 | case 0: case 1: case 2: case 3: | 47 | case 0: case 1: case 2: case 3: |
@@ -39,14 +51,14 @@ static inline unsigned long mips_get_syscall_arg(unsigned long *arg, | |||
39 | 51 | ||
40 | #ifdef CONFIG_32BIT | 52 | #ifdef CONFIG_32BIT |
41 | case 4: case 5: case 6: case 7: | 53 | case 4: case 5: case 6: case 7: |
42 | return get_user(*arg, (int *)usp + 4 * n); | 54 | return get_user(*arg, (int *)usp + n); |
43 | #endif | 55 | #endif |
44 | 56 | ||
45 | #ifdef CONFIG_64BIT | 57 | #ifdef CONFIG_64BIT |
46 | case 4: case 5: case 6: case 7: | 58 | case 4: case 5: case 6: case 7: |
47 | #ifdef CONFIG_MIPS32_O32 | 59 | #ifdef CONFIG_MIPS32_O32 |
48 | if (test_thread_flag(TIF_32BIT_REGS)) | 60 | if (test_thread_flag(TIF_32BIT_REGS)) |
49 | return get_user(*arg, (int *)usp + 4 * n); | 61 | return get_user(*arg, (int *)usp + n); |
50 | else | 62 | else |
51 | #endif | 63 | #endif |
52 | *arg = regs->regs[4 + n]; | 64 | *arg = regs->regs[4 + n]; |
@@ -57,6 +69,8 @@ static inline unsigned long mips_get_syscall_arg(unsigned long *arg, | |||
57 | default: | 69 | default: |
58 | BUG(); | 70 | BUG(); |
59 | } | 71 | } |
72 | |||
73 | unreachable(); | ||
60 | } | 74 | } |
61 | 75 | ||
62 | static inline long syscall_get_return_value(struct task_struct *task, | 76 | static inline long syscall_get_return_value(struct task_struct *task, |
@@ -65,6 +79,12 @@ static inline long syscall_get_return_value(struct task_struct *task, | |||
65 | return regs->regs[2]; | 79 | return regs->regs[2]; |
66 | } | 80 | } |
67 | 81 | ||
82 | static inline void syscall_rollback(struct task_struct *task, | ||
83 | struct pt_regs *regs) | ||
84 | { | ||
85 | /* Do nothing */ | ||
86 | } | ||
87 | |||
68 | static inline void syscall_set_return_value(struct task_struct *task, | 88 | static inline void syscall_set_return_value(struct task_struct *task, |
69 | struct pt_regs *regs, | 89 | struct pt_regs *regs, |
70 | int error, long val) | 90 | int error, long val) |
@@ -83,11 +103,17 @@ static inline void syscall_get_arguments(struct task_struct *task, | |||
83 | unsigned int i, unsigned int n, | 103 | unsigned int i, unsigned int n, |
84 | unsigned long *args) | 104 | unsigned long *args) |
85 | { | 105 | { |
86 | unsigned long arg; | ||
87 | int ret; | 106 | int ret; |
107 | /* O32 ABI syscall() - Either 64-bit with O32 or 32-bit */ | ||
108 | if ((config_enabled(CONFIG_32BIT) || | ||
109 | test_tsk_thread_flag(task, TIF_32BIT_REGS)) && | ||
110 | (regs->regs[2] == __NR_syscall)) { | ||
111 | i++; | ||
112 | n++; | ||
113 | } | ||
88 | 114 | ||
89 | while (n--) | 115 | while (n--) |
90 | ret |= mips_get_syscall_arg(&arg, task, regs, i++); | 116 | ret |= mips_get_syscall_arg(args++, task, regs, i++); |
91 | 117 | ||
92 | /* | 118 | /* |
93 | * No way to communicate an error because this is a void function. | 119 | * No way to communicate an error because this is a void function. |
@@ -105,7 +131,8 @@ static inline int syscall_get_arch(void) | |||
105 | { | 131 | { |
106 | int arch = EM_MIPS; | 132 | int arch = EM_MIPS; |
107 | #ifdef CONFIG_64BIT | 133 | #ifdef CONFIG_64BIT |
108 | arch |= __AUDIT_ARCH_64BIT; | 134 | if (!test_thread_flag(TIF_32BIT_REGS)) |
135 | arch |= __AUDIT_ARCH_64BIT; | ||
109 | #endif | 136 | #endif |
110 | #if defined(__LITTLE_ENDIAN) | 137 | #if defined(__LITTLE_ENDIAN) |
111 | arch |= __AUDIT_ARCH_LE; | 138 | arch |= __AUDIT_ARCH_LE; |