0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef __ASM_MIPS_SYSCALL_H
0014 #define __ASM_MIPS_SYSCALL_H
0015
0016 #include <linux/compiler.h>
0017 #include <uapi/linux/audit.h>
0018 #include <linux/elf-em.h>
0019 #include <linux/kernel.h>
0020 #include <linux/sched.h>
0021 #include <linux/uaccess.h>
0022 #include <asm/ptrace.h>
0023 #include <asm/unistd.h>
0024
0025 #ifndef __NR_syscall
0026 #define __NR_syscall 4000
0027 #endif
0028
0029 static inline bool mips_syscall_is_indirect(struct task_struct *task,
0030 struct pt_regs *regs)
0031 {
0032
0033 return (IS_ENABLED(CONFIG_32BIT) ||
0034 test_tsk_thread_flag(task, TIF_32BIT_REGS)) &&
0035 (regs->regs[2] == __NR_syscall);
0036 }
0037
0038 static inline long syscall_get_nr(struct task_struct *task,
0039 struct pt_regs *regs)
0040 {
0041 return current_thread_info()->syscall;
0042 }
0043
0044 static inline void mips_syscall_update_nr(struct task_struct *task,
0045 struct pt_regs *regs)
0046 {
0047
0048
0049
0050
0051 if (mips_syscall_is_indirect(task, regs))
0052 task_thread_info(task)->syscall = regs->regs[4];
0053 else
0054 task_thread_info(task)->syscall = regs->regs[2];
0055 }
0056
0057 static inline void mips_get_syscall_arg(unsigned long *arg,
0058 struct task_struct *task, struct pt_regs *regs, unsigned int n)
0059 {
0060 unsigned long usp __maybe_unused = regs->regs[29];
0061
0062 switch (n) {
0063 case 0: case 1: case 2: case 3:
0064 *arg = regs->regs[4 + n];
0065
0066 return;
0067
0068 #ifdef CONFIG_32BIT
0069 case 4: case 5: case 6: case 7:
0070 get_user(*arg, (int *)usp + n);
0071 return;
0072 #endif
0073
0074 #ifdef CONFIG_64BIT
0075 case 4: case 5: case 6: case 7:
0076 #ifdef CONFIG_MIPS32_O32
0077 if (test_tsk_thread_flag(task, TIF_32BIT_REGS))
0078 get_user(*arg, (int *)usp + n);
0079 else
0080 #endif
0081 *arg = regs->regs[4 + n];
0082
0083 return;
0084 #endif
0085
0086 default:
0087 BUG();
0088 }
0089
0090 unreachable();
0091 }
0092
0093 static inline long syscall_get_error(struct task_struct *task,
0094 struct pt_regs *regs)
0095 {
0096 return regs->regs[7] ? -regs->regs[2] : 0;
0097 }
0098
0099 static inline long syscall_get_return_value(struct task_struct *task,
0100 struct pt_regs *regs)
0101 {
0102 return regs->regs[2];
0103 }
0104
0105 static inline void syscall_rollback(struct task_struct *task,
0106 struct pt_regs *regs)
0107 {
0108
0109 }
0110
0111 static inline void syscall_set_return_value(struct task_struct *task,
0112 struct pt_regs *regs,
0113 int error, long val)
0114 {
0115 if (error) {
0116 regs->regs[2] = -error;
0117 regs->regs[7] = 1;
0118 } else {
0119 regs->regs[2] = val;
0120 regs->regs[7] = 0;
0121 }
0122 }
0123
0124 static inline void syscall_get_arguments(struct task_struct *task,
0125 struct pt_regs *regs,
0126 unsigned long *args)
0127 {
0128 unsigned int i = 0;
0129 unsigned int n = 6;
0130
0131
0132 if (mips_syscall_is_indirect(task, regs))
0133 i++;
0134
0135 while (n--)
0136 mips_get_syscall_arg(args++, task, regs, i++);
0137 }
0138
0139 extern const unsigned long sys_call_table[];
0140 extern const unsigned long sys32_call_table[];
0141 extern const unsigned long sysn32_call_table[];
0142
0143 static inline int syscall_get_arch(struct task_struct *task)
0144 {
0145 int arch = AUDIT_ARCH_MIPS;
0146 #ifdef CONFIG_64BIT
0147 if (!test_tsk_thread_flag(task, TIF_32BIT_REGS)) {
0148 arch |= __AUDIT_ARCH_64BIT;
0149
0150 if (test_tsk_thread_flag(task, TIF_32BIT_ADDR))
0151 arch |= __AUDIT_ARCH_CONVENTION_MIPS64_N32;
0152 }
0153 #endif
0154 #if defined(__LITTLE_ENDIAN)
0155 arch |= __AUDIT_ARCH_LE;
0156 #endif
0157 return arch;
0158 }
0159
0160 #endif