Commit | Line | Data |
---|---|---|
19e2e172 | 1 | /* |
c0ff3c53 RB |
2 | * Access to user system call parameters and results |
3 | * | |
19e2e172 RB |
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 | * | |
c0ff3c53 RB |
8 | * See asm-generic/syscall.h for descriptions of what we must do here. |
9 | * | |
19e2e172 RB |
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 | ||
bec9b2b2 RB |
16 | #include <linux/audit.h> |
17 | #include <linux/elf-em.h> | |
c0ff3c53 RB |
18 | #include <linux/kernel.h> |
19 | #include <linux/sched.h> | |
20 | #include <linux/uaccess.h> | |
21 | #include <asm/ptrace.h> | |
22 | ||
23 | static inline long syscall_get_nr(struct task_struct *task, | |
24 | struct pt_regs *regs) | |
25 | { | |
26 | return regs->regs[2]; | |
27 | } | |
28 | ||
29 | static inline unsigned long mips_get_syscall_arg(unsigned long *arg, | |
30 | struct task_struct *task, struct pt_regs *regs, unsigned int n) | |
31 | { | |
63238f2c | 32 | unsigned long usp __maybe_unused = regs->regs[29]; |
c0ff3c53 RB |
33 | |
34 | switch (n) { | |
35 | case 0: case 1: case 2: case 3: | |
36 | *arg = regs->regs[4 + n]; | |
37 | ||
38 | return 0; | |
39 | ||
40 | #ifdef CONFIG_32BIT | |
41 | case 4: case 5: case 6: case 7: | |
42 | return get_user(*arg, (int *)usp + 4 * n); | |
43 | #endif | |
44 | ||
45 | #ifdef CONFIG_64BIT | |
46 | case 4: case 5: case 6: case 7: | |
47 | #ifdef CONFIG_MIPS32_O32 | |
48 | if (test_thread_flag(TIF_32BIT_REGS)) | |
49 | return get_user(*arg, (int *)usp + 4 * n); | |
50 | else | |
51 | #endif | |
52 | *arg = regs->regs[4 + n]; | |
53 | ||
54 | return 0; | |
55 | #endif | |
56 | ||
57 | default: | |
58 | BUG(); | |
59 | } | |
60 | } | |
61 | ||
1d7bf993 RB |
62 | static inline long syscall_get_return_value(struct task_struct *task, |
63 | struct pt_regs *regs) | |
64 | { | |
65 | return regs->regs[2]; | |
66 | } | |
67 | ||
22feadbe MC |
68 | static inline void syscall_rollback(struct task_struct *task, |
69 | struct pt_regs *regs) | |
70 | { | |
71 | /* Do nothing */ | |
72 | } | |
73 | ||
1d7bf993 RB |
74 | static inline void syscall_set_return_value(struct task_struct *task, |
75 | struct pt_regs *regs, | |
76 | int error, long val) | |
77 | { | |
78 | if (error) { | |
79 | regs->regs[2] = -error; | |
80 | regs->regs[7] = -1; | |
81 | } else { | |
82 | regs->regs[2] = val; | |
83 | regs->regs[7] = 0; | |
84 | } | |
85 | } | |
86 | ||
c0ff3c53 RB |
87 | static inline void syscall_get_arguments(struct task_struct *task, |
88 | struct pt_regs *regs, | |
89 | unsigned int i, unsigned int n, | |
90 | unsigned long *args) | |
91 | { | |
92 | unsigned long arg; | |
93 | int ret; | |
94 | ||
95 | while (n--) | |
96 | ret |= mips_get_syscall_arg(&arg, task, regs, i++); | |
97 | ||
98 | /* | |
99 | * No way to communicate an error because this is a void function. | |
100 | */ | |
101 | #if 0 | |
102 | return ret; | |
103 | #endif | |
104 | } | |
105 | ||
19e2e172 RB |
106 | extern const unsigned long sys_call_table[]; |
107 | extern const unsigned long sys32_call_table[]; | |
108 | extern const unsigned long sysn32_call_table[]; | |
109 | ||
bec9b2b2 RB |
110 | static inline int __syscall_get_arch(void) |
111 | { | |
112 | int arch = EM_MIPS; | |
113 | #ifdef CONFIG_64BIT | |
114 | arch |= __AUDIT_ARCH_64BIT; | |
115 | #endif | |
116 | #if defined(__LITTLE_ENDIAN) | |
117 | arch |= __AUDIT_ARCH_LE; | |
118 | #endif | |
119 | return arch; | |
120 | } | |
121 | ||
19e2e172 | 122 | #endif /* __ASM_MIPS_SYSCALL_H */ |