diff options
Diffstat (limited to 'arch/x86/include/asm/syscall.h')
-rw-r--r-- | arch/x86/include/asm/syscall.h | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/arch/x86/include/asm/syscall.h b/arch/x86/include/asm/syscall.h new file mode 100644 index 000000000000..04c47dc5597c --- /dev/null +++ b/arch/x86/include/asm/syscall.h | |||
@@ -0,0 +1,211 @@ | |||
1 | /* | ||
2 | * Access to user system call parameters and results | ||
3 | * | ||
4 | * Copyright (C) 2008 Red Hat, Inc. All rights reserved. | ||
5 | * | ||
6 | * This copyrighted material is made available to anyone wishing to use, | ||
7 | * modify, copy, or redistribute it subject to the terms and conditions | ||
8 | * of the GNU General Public License v.2. | ||
9 | * | ||
10 | * See asm-generic/syscall.h for descriptions of what we must do here. | ||
11 | */ | ||
12 | |||
13 | #ifndef _ASM_SYSCALL_H | ||
14 | #define _ASM_SYSCALL_H 1 | ||
15 | |||
16 | #include <linux/sched.h> | ||
17 | #include <linux/err.h> | ||
18 | |||
19 | static inline long syscall_get_nr(struct task_struct *task, | ||
20 | struct pt_regs *regs) | ||
21 | { | ||
22 | /* | ||
23 | * We always sign-extend a -1 value being set here, | ||
24 | * so this is always either -1L or a syscall number. | ||
25 | */ | ||
26 | return regs->orig_ax; | ||
27 | } | ||
28 | |||
29 | static inline void syscall_rollback(struct task_struct *task, | ||
30 | struct pt_regs *regs) | ||
31 | { | ||
32 | regs->ax = regs->orig_ax; | ||
33 | } | ||
34 | |||
35 | static inline long syscall_get_error(struct task_struct *task, | ||
36 | struct pt_regs *regs) | ||
37 | { | ||
38 | unsigned long error = regs->ax; | ||
39 | #ifdef CONFIG_IA32_EMULATION | ||
40 | /* | ||
41 | * TS_COMPAT is set for 32-bit syscall entries and then | ||
42 | * remains set until we return to user mode. | ||
43 | */ | ||
44 | if (task_thread_info(task)->status & TS_COMPAT) | ||
45 | /* | ||
46 | * Sign-extend the value so (int)-EFOO becomes (long)-EFOO | ||
47 | * and will match correctly in comparisons. | ||
48 | */ | ||
49 | error = (long) (int) error; | ||
50 | #endif | ||
51 | return IS_ERR_VALUE(error) ? error : 0; | ||
52 | } | ||
53 | |||
54 | static inline long syscall_get_return_value(struct task_struct *task, | ||
55 | struct pt_regs *regs) | ||
56 | { | ||
57 | return regs->ax; | ||
58 | } | ||
59 | |||
60 | static inline void syscall_set_return_value(struct task_struct *task, | ||
61 | struct pt_regs *regs, | ||
62 | int error, long val) | ||
63 | { | ||
64 | regs->ax = (long) error ?: val; | ||
65 | } | ||
66 | |||
67 | #ifdef CONFIG_X86_32 | ||
68 | |||
69 | static inline void syscall_get_arguments(struct task_struct *task, | ||
70 | struct pt_regs *regs, | ||
71 | unsigned int i, unsigned int n, | ||
72 | unsigned long *args) | ||
73 | { | ||
74 | BUG_ON(i + n > 6); | ||
75 | memcpy(args, ®s->bx + i, n * sizeof(args[0])); | ||
76 | } | ||
77 | |||
78 | static inline void syscall_set_arguments(struct task_struct *task, | ||
79 | struct pt_regs *regs, | ||
80 | unsigned int i, unsigned int n, | ||
81 | const unsigned long *args) | ||
82 | { | ||
83 | BUG_ON(i + n > 6); | ||
84 | memcpy(®s->bx + i, args, n * sizeof(args[0])); | ||
85 | } | ||
86 | |||
87 | #else /* CONFIG_X86_64 */ | ||
88 | |||
89 | static inline void syscall_get_arguments(struct task_struct *task, | ||
90 | struct pt_regs *regs, | ||
91 | unsigned int i, unsigned int n, | ||
92 | unsigned long *args) | ||
93 | { | ||
94 | # ifdef CONFIG_IA32_EMULATION | ||
95 | if (task_thread_info(task)->status & TS_COMPAT) | ||
96 | switch (i + n) { | ||
97 | case 6: | ||
98 | if (!n--) break; | ||
99 | *args++ = regs->bp; | ||
100 | case 5: | ||
101 | if (!n--) break; | ||
102 | *args++ = regs->di; | ||
103 | case 4: | ||
104 | if (!n--) break; | ||
105 | *args++ = regs->si; | ||
106 | case 3: | ||
107 | if (!n--) break; | ||
108 | *args++ = regs->dx; | ||
109 | case 2: | ||
110 | if (!n--) break; | ||
111 | *args++ = regs->cx; | ||
112 | case 1: | ||
113 | if (!n--) break; | ||
114 | *args++ = regs->bx; | ||
115 | case 0: | ||
116 | if (!n--) break; | ||
117 | default: | ||
118 | BUG(); | ||
119 | break; | ||
120 | } | ||
121 | else | ||
122 | # endif | ||
123 | switch (i + n) { | ||
124 | case 6: | ||
125 | if (!n--) break; | ||
126 | *args++ = regs->r9; | ||
127 | case 5: | ||
128 | if (!n--) break; | ||
129 | *args++ = regs->r8; | ||
130 | case 4: | ||
131 | if (!n--) break; | ||
132 | *args++ = regs->r10; | ||
133 | case 3: | ||
134 | if (!n--) break; | ||
135 | *args++ = regs->dx; | ||
136 | case 2: | ||
137 | if (!n--) break; | ||
138 | *args++ = regs->si; | ||
139 | case 1: | ||
140 | if (!n--) break; | ||
141 | *args++ = regs->di; | ||
142 | case 0: | ||
143 | if (!n--) break; | ||
144 | default: | ||
145 | BUG(); | ||
146 | break; | ||
147 | } | ||
148 | } | ||
149 | |||
150 | static inline void syscall_set_arguments(struct task_struct *task, | ||
151 | struct pt_regs *regs, | ||
152 | unsigned int i, unsigned int n, | ||
153 | const unsigned long *args) | ||
154 | { | ||
155 | # ifdef CONFIG_IA32_EMULATION | ||
156 | if (task_thread_info(task)->status & TS_COMPAT) | ||
157 | switch (i + n) { | ||
158 | case 6: | ||
159 | if (!n--) break; | ||
160 | regs->bp = *args++; | ||
161 | case 5: | ||
162 | if (!n--) break; | ||
163 | regs->di = *args++; | ||
164 | case 4: | ||
165 | if (!n--) break; | ||
166 | regs->si = *args++; | ||
167 | case 3: | ||
168 | if (!n--) break; | ||
169 | regs->dx = *args++; | ||
170 | case 2: | ||
171 | if (!n--) break; | ||
172 | regs->cx = *args++; | ||
173 | case 1: | ||
174 | if (!n--) break; | ||
175 | regs->bx = *args++; | ||
176 | case 0: | ||
177 | if (!n--) break; | ||
178 | default: | ||
179 | BUG(); | ||
180 | } | ||
181 | else | ||
182 | # endif | ||
183 | switch (i + n) { | ||
184 | case 6: | ||
185 | if (!n--) break; | ||
186 | regs->r9 = *args++; | ||
187 | case 5: | ||
188 | if (!n--) break; | ||
189 | regs->r8 = *args++; | ||
190 | case 4: | ||
191 | if (!n--) break; | ||
192 | regs->r10 = *args++; | ||
193 | case 3: | ||
194 | if (!n--) break; | ||
195 | regs->dx = *args++; | ||
196 | case 2: | ||
197 | if (!n--) break; | ||
198 | regs->si = *args++; | ||
199 | case 1: | ||
200 | if (!n--) break; | ||
201 | regs->di = *args++; | ||
202 | case 0: | ||
203 | if (!n--) break; | ||
204 | default: | ||
205 | BUG(); | ||
206 | } | ||
207 | } | ||
208 | |||
209 | #endif /* CONFIG_X86_32 */ | ||
210 | |||
211 | #endif /* _ASM_SYSCALL_H */ | ||