4 #define KERNEL_CS (0x8)
5 #define KERNEL_DS (0x10)
6 #define USER_CS (0x18 + 0x3)
7 #define USER_DS (0x20 + 0x3)
8 #define RESERVED_FOR_TSS (0x28)
9 #define PCR_SELECTOR (0x30)
10 #define TEB_SELECTOR (0x38 + 0x3)
12 //#define USER_CS (0x8+0x3)
13 //#define USER_DS (0x10+0x3)
14 //#define ZERO_DS 0x18
15 //#define KERNEL_CS 0x20
16 //#define KERNEL_DS 0x28
21 * Uh, these should become the main single-value transfer routines..
22 * They automatically use the right size if we just have the right
25 #define put_user(x,ptr) __put_user((unsigned long)(x),(ptr),sizeof(*(ptr)))
26 #define get_user(ptr) ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr))))
29 * This is a silly but good way to make sure that
30 * the __put_user function is indeed always optimized,
31 * and that we use the correct sizes..
33 extern int bad_user_access_length(void);
36 * dummy pointer type structure.. gcc won't try to do something strange
39 struct __segment_dummy
{ unsigned long a
[100]; };
40 #define __sd(x) ((struct __segment_dummy *) (x))
41 #define __const_sd(x) ((const struct __segment_dummy *) (x))
43 static inline void __put_user(unsigned long x
, void * y
, int size
)
47 __asm__ ("movb %b1,%%fs:%0" \
49 :"iq" ((unsigned char) x
), "m" (*__sd(y
)));
52 __asm__ ("movw %w1,%%fs:%0" \
54 :"ir" ((unsigned short) x
), "m" (*__sd(y
)));
57 __asm__ ("movl %1,%%fs:%0" \
59 :"ir" (x
), "m" (*__sd(y
)));
62 bad_user_access_length();
66 static inline unsigned long __get_user(const void * y
, int size
)
72 __asm__ ("movb %%fs:%1,%b0" \
74 :"m" (*__const_sd(y
)));
75 return (unsigned char) result
;
77 __asm__ ("movw %%fs:%1,%w0" \
79 :"m" (*__const_sd(y
)));
80 return (unsigned short) result
;
82 __asm__ ("movl %%fs:%1,%0" \
84 :"m" (*__const_sd(y
)));
87 return bad_user_access_length();
91 static inline void __generic_memcpy_tofs(void * to
, const void * from
, unsigned long n
)
113 :"0" (n
),"D" ((long) to
),"S" ((long) from
) \
117 static inline void __constant_memcpy_tofs(void * to
, const void * from
, unsigned long n
)
123 __put_user(*(const char *) from
, (char *) to
, 1);
126 __put_user(*(const short *) from
, (short *) to
, 2);
129 __put_user(*(const short *) from
, (short *) to
, 2);
130 __put_user(*(2+(const char *) from
), 2+(char *) to
, 1);
133 __put_user(*(const int *) from
, (int *) to
, 4);
136 __put_user(*(const int *) from
, (int *) to
, 4);
137 __put_user(*(1+(const int *) from
), 1+(int *) to
, 4);
140 __put_user(*(const int *) from
, (int *) to
, 4);
141 __put_user(*(1+(const int *) from
), 1+(int *) to
, 4);
142 __put_user(*(2+(const int *) from
), 2+(int *) to
, 4);
145 __put_user(*(const int *) from
, (int *) to
, 4);
146 __put_user(*(1+(const int *) from
), 1+(int *) to
, 4);
147 __put_user(*(2+(const int *) from
), 2+(int *) to
, 4);
148 __put_user(*(3+(const int *) from
), 3+(int *) to
, 4);
160 :"c" (n/4),"D" ((long) to),"S" ((long) from) \
174 COMMON("movsw\n\tmovsb\n\t");
180 static inline void __generic_memcpy_fromfs(void * to
, const void * from
, unsigned long n
)
198 :"0" (n
),"D" ((long) to
),"S" ((long) from
)
199 :"cx","di","si", "memory");
202 static inline void __constant_memcpy_fromfs(void * to
, const void * from
, unsigned long n
)
208 *(char *)to
= __get_user((const char *) from
, 1);
211 *(short *)to
= __get_user((const short *) from
, 2);
214 *(short *) to
= __get_user((const short *) from
, 2);
215 *((char *) to
+ 2) = __get_user(2+(const char *) from
, 1);
218 *(int *) to
= __get_user((const int *) from
, 4);
221 *(int *) to
= __get_user((const int *) from
, 4);
222 *(1+(int *) to
) = __get_user(1+(const int *) from
, 4);
225 *(int *) to
= __get_user((const int *) from
, 4);
226 *(1+(int *) to
) = __get_user(1+(const int *) from
, 4);
227 *(2+(int *) to
) = __get_user(2+(const int *) from
, 4);
230 *(int *) to
= __get_user((const int *) from
, 4);
231 *(1+(int *) to
) = __get_user(1+(const int *) from
, 4);
232 *(2+(int *) to
) = __get_user(2+(const int *) from
, 4);
233 *(3+(int *) to
) = __get_user(3+(const int *) from
, 4);
238 "rep ; fs ; movsl\n\t" \
241 :"c" (n/4),"D" ((long) to),"S" ((long) from) \
242 :"cx","di","si","memory")
249 COMMON("fs ; movsb");
252 COMMON("fs ; movsw");
255 COMMON("fs ; movsw\n\tfs ; movsb");
261 #define memcpy_fromfs(to, from, n) \
262 (__builtin_constant_p(n) ? \
263 __constant_memcpy_fromfs((to),(from),(n)) : \
264 __generic_memcpy_fromfs((to),(from),(n)))
266 #define memcpy_tofs(to, from, n) \
267 (__builtin_constant_p(n) ? \
268 __constant_memcpy_tofs((to),(from),(n)) : \
269 __generic_memcpy_tofs((to),(from),(n)))
272 * These are deprecated..
274 * Use "put_user()" and "get_user()" with the proper pointer types instead.
277 #define get_fs_byte(addr) __get_user((const unsigned char *)(addr),1)
278 #define get_fs_word(addr) __get_user((const unsigned short *)(addr),2)
279 #define get_fs_long(addr) __get_user((const unsigned int *)(addr),4)
281 #define put_fs_byte(x,addr) __put_user((x),(unsigned char *)(addr),1)
282 #define put_fs_word(x,addr) __put_user((x),(unsigned short *)(addr),2)
283 #define put_fs_long(x,addr) __put_user((x),(unsigned int *)(addr),4)
285 #ifdef WE_REALLY_WANT_TO_USE_A_BROKEN_INTERFACE
287 static inline unsigned short get_user_word(const short *addr
)
289 return __get_user(addr
, 2);
292 static inline unsigned char get_user_byte(const char * addr
)
294 return __get_user(addr
,1);
297 static inline unsigned long get_user_long(const int *addr
)
299 return __get_user(addr
, 4);
302 static inline void put_user_byte(char val
,char *addr
)
304 __put_user(val
, addr
, 1);
307 static inline void put_user_word(short val
,short * addr
)
309 __put_user(val
, addr
, 2);
312 static inline void put_user_long(unsigned long val
,int * addr
)
314 __put_user(val
, addr
, 4);
320 * Someone who knows GNU asm better than I should double check the following.
321 * It seems to work, but I don't know if I'm doing something subtly wrong.
323 * [ nothing wrong here, Linus: I just changed the ax to be any reg ]
326 static inline unsigned long get_fs(void)
329 __asm__("mov %%fs,%w0":"=r" (_v
):"0" (0));
333 static inline unsigned long get_ds(void)
336 __asm__("mov %%ds,%w0":"=r" (_v
):"0" (0));
340 static inline void set_fs(unsigned long val
)
342 __asm__
__volatile__("mov %w0,%%fs": /* no output */ :"r" (val
));
345 static inline void set_ds(unsigned long val
)
347 __asm__
__volatile__("mov %w0,%%ds": /* no output */ :"r" (val
));
351 #endif /* __ASSEMBLY__ */
353 #endif /* _ASM_SEGMENT_H */