]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - include/asm-x86/syscall.h
Merge branch 'linus' into x86/tracehook
[linux-2.6-omap-h63xx.git] / include / asm-x86 / syscall.h
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
18 static inline long syscall_get_nr(struct task_struct *task,
19                                   struct pt_regs *regs)
20 {
21         /*
22          * We always sign-extend a -1 value being set here,
23          * so this is always either -1L or a syscall number.
24          */
25         return regs->orig_ax;
26 }
27
28 static inline void syscall_rollback(struct task_struct *task,
29                                     struct pt_regs *regs)
30 {
31         regs->ax = regs->orig_ax;
32 }
33
34 static inline long syscall_get_error(struct task_struct *task,
35                                      struct pt_regs *regs)
36 {
37         unsigned long error = regs->ax;
38 #ifdef CONFIG_IA32_EMULATION
39         /*
40          * TS_COMPAT is set for 32-bit syscall entries and then
41          * remains set until we return to user mode.
42          */
43         if (task_thread_info(task)->status & TS_COMPAT)
44                 /*
45                  * Sign-extend the value so (int)-EFOO becomes (long)-EFOO
46                  * and will match correctly in comparisons.
47                  */
48                 error = (long) (int) error;
49 #endif
50         return error >= -4095L ? error : 0;
51 }
52
53 static inline long syscall_get_return_value(struct task_struct *task,
54                                             struct pt_regs *regs)
55 {
56         return regs->ax;
57 }
58
59 static inline void syscall_set_return_value(struct task_struct *task,
60                                             struct pt_regs *regs,
61                                             int error, long val)
62 {
63         regs->ax = (long) error ?: val;
64 }
65
66 #ifdef CONFIG_X86_32
67
68 static inline void syscall_get_arguments(struct task_struct *task,
69                                          struct pt_regs *regs,
70                                          unsigned int i, unsigned int n,
71                                          unsigned long *args)
72 {
73         BUG_ON(i + n > 6);
74         memcpy(args, &regs->bx + i, n * sizeof(args[0]));
75 }
76
77 static inline void syscall_set_arguments(struct task_struct *task,
78                                          struct pt_regs *regs,
79                                          unsigned int i, unsigned int n,
80                                          const unsigned long *args)
81 {
82         BUG_ON(i + n > 6);
83         memcpy(&regs->bx + i, args, n * sizeof(args[0]));
84 }
85
86 #else    /* CONFIG_X86_64 */
87
88 static inline void syscall_get_arguments(struct task_struct *task,
89                                          struct pt_regs *regs,
90                                          unsigned int i, unsigned int n,
91                                          unsigned long *args)
92 {
93 # ifdef CONFIG_IA32_EMULATION
94         if (task_thread_info(task)->status & TS_COMPAT)
95                 switch (i + n) {
96                 case 6:
97                         if (!n--) break;
98                         *args++ = regs->bp;
99                 case 5:
100                         if (!n--) break;
101                         *args++ = regs->di;
102                 case 4:
103                         if (!n--) break;
104                         *args++ = regs->si;
105                 case 3:
106                         if (!n--) break;
107                         *args++ = regs->dx;
108                 case 2:
109                         if (!n--) break;
110                         *args++ = regs->cx;
111                 case 1:
112                         if (!n--) break;
113                         *args++ = regs->bx;
114                 case 0:
115                         if (!n--) break;
116                 default:
117                         BUG();
118                         break;
119                 }
120         else
121 # endif
122                 switch (i + n) {
123                 case 6:
124                         if (!n--) break;
125                         *args++ = regs->r9;
126                 case 5:
127                         if (!n--) break;
128                         *args++ = regs->r8;
129                 case 4:
130                         if (!n--) break;
131                         *args++ = regs->r10;
132                 case 3:
133                         if (!n--) break;
134                         *args++ = regs->dx;
135                 case 2:
136                         if (!n--) break;
137                         *args++ = regs->si;
138                 case 1:
139                         if (!n--) break;
140                         *args++ = regs->di;
141                 case 0:
142                         if (!n--) break;
143                 default:
144                         BUG();
145                         break;
146                 }
147 }
148
149 static inline void syscall_set_arguments(struct task_struct *task,
150                                          struct pt_regs *regs,
151                                          unsigned int i, unsigned int n,
152                                          const unsigned long *args)
153 {
154 # ifdef CONFIG_IA32_EMULATION
155         if (task_thread_info(task)->status & TS_COMPAT)
156                 switch (i + n) {
157                 case 6:
158                         if (!n--) break;
159                         regs->bp = *args++;
160                 case 5:
161                         if (!n--) break;
162                         regs->di = *args++;
163                 case 4:
164                         if (!n--) break;
165                         regs->si = *args++;
166                 case 3:
167                         if (!n--) break;
168                         regs->dx = *args++;
169                 case 2:
170                         if (!n--) break;
171                         regs->cx = *args++;
172                 case 1:
173                         if (!n--) break;
174                         regs->bx = *args++;
175                 case 0:
176                         if (!n--) break;
177                 default:
178                         BUG();
179                 }
180         else
181 # endif
182                 switch (i + n) {
183                 case 6:
184                         if (!n--) break;
185                         regs->r9 = *args++;
186                 case 5:
187                         if (!n--) break;
188                         regs->r8 = *args++;
189                 case 4:
190                         if (!n--) break;
191                         regs->r10 = *args++;
192                 case 3:
193                         if (!n--) break;
194                         regs->dx = *args++;
195                 case 2:
196                         if (!n--) break;
197                         regs->si = *args++;
198                 case 1:
199                         if (!n--) break;
200                         regs->di = *args++;
201                 case 0:
202                         if (!n--) break;
203                 default:
204                         BUG();
205                 }
206 }
207
208 #endif  /* CONFIG_X86_32 */
209
210 #endif  /* _ASM_SYSCALL_H */