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; |
