root/arch/mips/include/asm/syscall.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. mips_syscall_is_indirect
  2. syscall_get_nr
  3. mips_syscall_update_nr
  4. mips_get_syscall_arg
  5. syscall_get_error
  6. syscall_get_return_value
  7. syscall_rollback
  8. syscall_set_return_value
  9. syscall_get_arguments
  10. syscall_get_arch

   1 /*
   2  * Access to user system call parameters and results
   3  *
   4  * This file is subject to the terms and conditions of the GNU General Public
   5  * License.  See the file "COPYING" in the main directory of this archive
   6  * for more details.
   7  *
   8  * See asm-generic/syscall.h for descriptions of what we must do here.
   9  *
  10  * Copyright (C) 2012 Ralf Baechle <ralf@linux-mips.org>
  11  */
  12 
  13 #ifndef __ASM_MIPS_SYSCALL_H
  14 #define __ASM_MIPS_SYSCALL_H
  15 
  16 #include <linux/compiler.h>
  17 #include <uapi/linux/audit.h>
  18 #include <linux/elf-em.h>
  19 #include <linux/kernel.h>
  20 #include <linux/sched.h>
  21 #include <linux/uaccess.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
  28 
  29 static inline bool mips_syscall_is_indirect(struct task_struct *task,
  30                                             struct pt_regs *regs)
  31 {
  32         /* O32 ABI syscall() - Either 64-bit with O32 or 32-bit */
  33         return (IS_ENABLED(CONFIG_32BIT) ||
  34                 test_tsk_thread_flag(task, TIF_32BIT_REGS)) &&
  35                 (regs->regs[2] == __NR_syscall);
  36 }
  37 
  38 static inline long syscall_get_nr(struct task_struct *task,
  39                                   struct pt_regs *regs)
  40 {
  41         return current_thread_info()->syscall;
  42 }
  43 
  44 static inline void mips_syscall_update_nr(struct task_struct *task,
  45                                           struct pt_regs *regs)
  46 {
  47         /*
  48          * v0 is the system call number, except for O32 ABI syscall(), where it
  49          * ends up in a0.
  50          */
  51         if (mips_syscall_is_indirect(task, regs))
  52                 task_thread_info(task)->syscall = regs->regs[4];
  53         else
  54                 task_thread_info(task)->syscall = regs->regs[2];
  55 }
  56 
  57 static inline void mips_get_syscall_arg(unsigned long *arg,
  58         struct task_struct *task, struct pt_regs *regs, unsigned int n)
  59 {
  60         unsigned long usp __maybe_unused = regs->regs[29];
  61 
  62         switch (n) {
  63         case 0: case 1: case 2: case 3:
  64                 *arg = regs->regs[4 + n];
  65 
  66                 return;
  67 
  68 #ifdef CONFIG_32BIT
  69         case 4: case 5: case 6: case 7:
  70                 get_user(*arg, (int *)usp + n);
  71                 return;
  72 #endif
  73 
  74 #ifdef CONFIG_64BIT
  75         case 4: case 5: case 6: case 7:
  76 #ifdef CONFIG_MIPS32_O32
  77                 if (test_tsk_thread_flag(task, TIF_32BIT_REGS))
  78                         get_user(*arg, (int *)usp + n);
  79                 else
  80 #endif
  81                         *arg = regs->regs[4 + n];
  82 
  83                 return;
  84 #endif
  85 
  86         default:
  87                 BUG();
  88         }
  89 
  90         unreachable();
  91 }
  92 
  93 static inline long syscall_get_error(struct task_struct *task,
  94                                      struct pt_regs *regs)
  95 {
  96         return regs->regs[7] ? -regs->regs[2] : 0;
  97 }
  98 
  99 static inline long syscall_get_return_value(struct task_struct *task,
 100                                             struct pt_regs *regs)
 101 {
 102         return regs->regs[2];
 103 }
 104 
 105 static inline void syscall_rollback(struct task_struct *task,
 106                                     struct pt_regs *regs)
 107 {
 108         /* Do nothing */
 109 }
 110 
 111 static inline void syscall_set_return_value(struct task_struct *task,
 112                                             struct pt_regs *regs,
 113                                             int error, long val)
 114 {
 115         if (error) {
 116                 regs->regs[2] = -error;
 117                 regs->regs[7] = 1;
 118         } else {
 119                 regs->regs[2] = val;
 120                 regs->regs[7] = 0;
 121         }
 122 }
 123 
 124 static inline void syscall_get_arguments(struct task_struct *task,
 125                                          struct pt_regs *regs,
 126                                          unsigned long *args)
 127 {
 128         unsigned int i = 0;
 129         unsigned int n = 6;
 130 
 131         /* O32 ABI syscall() */
 132         if (mips_syscall_is_indirect(task, regs))
 133                 i++;
 134 
 135         while (n--)
 136                 mips_get_syscall_arg(args++, task, regs, i++);
 137 }
 138 
 139 extern const unsigned long sys_call_table[];
 140 extern const unsigned long sys32_call_table[];
 141 extern const unsigned long sysn32_call_table[];
 142 
 143 static inline int syscall_get_arch(struct task_struct *task)
 144 {
 145         int arch = AUDIT_ARCH_MIPS;
 146 #ifdef CONFIG_64BIT
 147         if (!test_tsk_thread_flag(task, TIF_32BIT_REGS)) {
 148                 arch |= __AUDIT_ARCH_64BIT;
 149                 /* N32 sets only TIF_32BIT_ADDR */
 150                 if (test_tsk_thread_flag(task, TIF_32BIT_ADDR))
 151                         arch |= __AUDIT_ARCH_CONVENTION_MIPS64_N32;
 152         }
 153 #endif
 154 #if defined(__LITTLE_ENDIAN)
 155         arch |=  __AUDIT_ARCH_LE;
 156 #endif
 157         return arch;
 158 }
 159 
 160 #endif  /* __ASM_MIPS_SYSCALL_H */

/* [<][>][^][v][top][bottom][index][help] */