root/include/asm-i386/segment.h

/* [previous][next][first][last][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. __put_user
  2. __get_user
  3. __generic_memcpy_tofs
  4. __constant_memcpy_tofs
  5. __generic_memcpy_fromfs
  6. __constant_memcpy_fromfs
  7. get_user_word
  8. get_user_byte
  9. get_user_long
  10. put_user_byte
  11. put_user_word
  12. put_user_long
  13. get_fs
  14. get_ds
  15. set_fs

   1 #ifndef _ASM_SEGMENT_H
   2 #define _ASM_SEGMENT_H
   3 
   4 #define KERNEL_CS       0x10
   5 #define KERNEL_DS       0x18
   6 
   7 #define USER_CS         0x23
   8 #define USER_DS         0x2B
   9 
  10 #ifndef __ASSEMBLY__
  11 
  12 /*
  13  * Uh, these should become the main single-value transfer routines..
  14  * They automatically use the right size if we just have the right
  15  * pointer type..
  16  */
  17 #define put_user(x,ptr) __put_user((unsigned long)(x),(ptr),sizeof(*(ptr)))
  18 #define get_user(ptr) ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr))))
  19 
  20 /*
  21  * This is a silly but good way to make sure that
  22  * the __put_user function is indeed always optimized,
  23  * and that we use the correct sizes..
  24  */
  25 extern int bad_user_access_length(void);
  26 
  27 /*
  28  * dummy pointer type structure.. gcc won't try to do something strange
  29  * this way..
  30  */
  31 struct __segment_dummy { unsigned long a[100]; };
  32 #define __sd(x) ((struct __segment_dummy *) (x))
  33 #define __const_sd(x) ((const struct __segment_dummy *) (x))
  34 
  35 static inline void __put_user(unsigned long x, void * y, int size)
     /* [previous][next][first][last][top][bottom][index][help] */
  36 {
  37         switch (size) {
  38                 case 1:
  39                         __asm__ ("movb %b1,%%fs:%0"
  40                                 :"=m" (*__sd(y))
  41                                 :"iq" ((unsigned char) x), "m" (*__sd(y)));
  42                         break;
  43                 case 2:
  44                         __asm__ ("movw %w1,%%fs:%0"
  45                                 :"=m" (*__sd(y))
  46                                 :"ir" ((unsigned short) x), "m" (*__sd(y)));
  47                         break;
  48                 case 4:
  49                         __asm__ ("movl %1,%%fs:%0"
  50                                 :"=m" (*__sd(y))
  51                                 :"ir" (x), "m" (*__sd(y)));
  52                         break;
  53                 default:
  54                         bad_user_access_length();
  55         }
  56 }
  57 
  58 static inline unsigned long __get_user(const void * y, int size)
     /* [previous][next][first][last][top][bottom][index][help] */
  59 {
  60         unsigned long result;
  61 
  62         switch (size) {
  63                 case 1:
  64                         __asm__ ("movb %%fs:%1,%b0"
  65                                 :"=q" (result)
  66                                 :"m" (*__const_sd(y)));
  67                         return (unsigned char) result;
  68                 case 2:
  69                         __asm__ ("movw %%fs:%1,%w0"
  70                                 :"=r" (result)
  71                                 :"m" (*__const_sd(y)));
  72                         return (unsigned short) result;
  73                 case 4:
  74                         __asm__ ("movl %%fs:%1,%0"
  75                                 :"=r" (result)
  76                                 :"m" (*__const_sd(y)));
  77                         return result;
  78                 default:
  79                         return bad_user_access_length();
  80         }
  81 }
  82 
  83 static inline void __generic_memcpy_tofs(void * to, const void * from, unsigned long n)
     /* [previous][next][first][last][top][bottom][index][help] */
  84 {
  85     __asm__ volatile
  86         ("      cld
  87                 push %%es
  88                 movw %%fs,%%cx
  89                 movw %%cx,%%es
  90                 cmpl $3,%0
  91                 jbe 1f
  92                 movl %%edi,%%ecx
  93                 negl %%ecx
  94                 andl $3,%%ecx
  95                 subl %%ecx,%0
  96                 rep; movsb
  97                 movl %0,%%ecx
  98                 shrl $2,%%ecx
  99                 rep; movsl
 100                 andl $3,%0
 101         1:      movl %0,%%ecx
 102                 rep; movsb
 103                 pop %%es"
 104         :"=abd" (n)
 105         :"0" (n),"D" ((long) to),"S" ((long) from)
 106         :"cx","di","si");
 107 }
 108 
 109 static inline void __constant_memcpy_tofs(void * to, const void * from, unsigned long n)
     /* [previous][next][first][last][top][bottom][index][help] */
 110 {
 111         switch (n) {
 112                 case 0:
 113                         return;
 114                 case 1:
 115                         __put_user(*(const char *) from, (char *) to, 1);
 116                         return;
 117                 case 2:
 118                         __put_user(*(const short *) from, (short *) to, 2);
 119                         return;
 120                 case 3:
 121                         __put_user(*(const short *) from, (short *) to, 2);
 122                         __put_user(*(2+(const char *) from), 2+(char *) to, 1);
 123                         return;
 124                 case 4:
 125                         __put_user(*(const int *) from, (int *) to, 4);
 126                         return;
 127                 case 8:
 128                         __put_user(*(const int *) from, (int *) to, 4);
 129                         __put_user(*(1+(const int *) from), 1+(int *) to, 4);
 130                         return;
 131                 case 12:
 132                         __put_user(*(const int *) from, (int *) to, 4);
 133                         __put_user(*(1+(const int *) from), 1+(int *) to, 4);
 134                         __put_user(*(2+(const int *) from), 2+(int *) to, 4);
 135                         return;
 136                 case 16:
 137                         __put_user(*(const int *) from, (int *) to, 4);
 138                         __put_user(*(1+(const int *) from), 1+(int *) to, 4);
 139                         __put_user(*(2+(const int *) from), 2+(int *) to, 4);
 140                         __put_user(*(3+(const int *) from), 3+(int *) to, 4);
 141                         return;
 142         }
 143 #define COMMON(x) \
 144 __asm__("cld\n\t" \
 145         "push %%es\n\t" \
 146         "push %%fs\n\t" \
 147         "pop %%es\n\t" \
 148         "rep ; movsl\n\t" \
 149         x \
 150         "pop %%es" \
 151         : /* no outputs */ \
 152         :"c" (n/4),"D" ((long) to),"S" ((long) from) \
 153         :"cx","di","si")
 154 
 155         switch (n % 4) {
 156                 case 0:
 157                         COMMON("");
 158                         return;
 159                 case 1:
 160                         COMMON("movsb\n\t");
 161                         return;
 162                 case 2:
 163                         COMMON("movsw\n\t");
 164                         return;
 165                 case 3:
 166                         COMMON("movsw\n\tmovsb\n\t");
 167                         return;
 168         }
 169 #undef COMMON
 170 }
 171 
 172 static inline void __generic_memcpy_fromfs(void * to, const void * from, unsigned long n)
     /* [previous][next][first][last][top][bottom][index][help] */
 173 {
 174     __asm__ volatile
 175         ("      cld
 176                 cmpl $3,%0
 177                 jbe 1f
 178                 movl %%edi,%%ecx
 179                 negl %%ecx
 180                 andl $3,%%ecx
 181                 subl %%ecx,%0
 182                 fs; rep; movsb
 183                 movl %0,%%ecx
 184                 shrl $2,%%ecx
 185                 fs; rep; movsl
 186                 andl $3,%0
 187         1:      movl %0,%%ecx
 188                 fs; rep; movsb"
 189         :"=abd" (n)
 190         :"0" (n),"D" ((long) to),"S" ((long) from)
 191         :"cx","di","si", "memory");
 192 }
 193 
 194 static inline void __constant_memcpy_fromfs(void * to, const void * from, unsigned long n)
     /* [previous][next][first][last][top][bottom][index][help] */
 195 {
 196         switch (n) {
 197                 case 0:
 198                         return;
 199                 case 1:
 200                         *(char *)to = __get_user((const char *) from, 1);
 201                         return;
 202                 case 2:
 203                         *(short *)to = __get_user((const short *) from, 2);
 204                         return;
 205                 case 3:
 206                         *(short *) to = __get_user((const short *) from, 2);
 207                         *((char *) to + 2) = __get_user(2+(const char *) from, 1);
 208                         return;
 209                 case 4:
 210                         *(int *) to = __get_user((const int *) from, 4);
 211                         return;
 212                 case 8:
 213                         *(int *) to = __get_user((const int *) from, 4);
 214                         *(1+(int *) to) = __get_user(1+(const int *) from, 4);
 215                         return;
 216                 case 12:
 217                         *(int *) to = __get_user((const int *) from, 4);
 218                         *(1+(int *) to) = __get_user(1+(const int *) from, 4);
 219                         *(2+(int *) to) = __get_user(2+(const int *) from, 4);
 220                         return;
 221                 case 16:
 222                         *(int *) to = __get_user((const int *) from, 4);
 223                         *(1+(int *) to) = __get_user(1+(const int *) from, 4);
 224                         *(2+(int *) to) = __get_user(2+(const int *) from, 4);
 225                         *(3+(int *) to) = __get_user(3+(const int *) from, 4);
 226                         return;
 227         }
 228 #define COMMON(x) \
 229 __asm__("cld\n\t" \
 230         "rep ; fs ; movsl\n\t" \
 231         x \
 232         : /* no outputs */ \
 233         :"c" (n/4),"D" ((long) to),"S" ((long) from) \
 234         :"cx","di","si","memory")
 235 
 236         switch (n % 4) {
 237                 case 0:
 238                         COMMON("");
 239                         return;
 240                 case 1:
 241                         COMMON("fs ; movsb");
 242                         return;
 243                 case 2:
 244                         COMMON("fs ; movsw");
 245                         return;
 246                 case 3:
 247                         COMMON("fs ; movsw\n\tfs ; movsb");
 248                         return;
 249         }
 250 #undef COMMON
 251 }
 252 
 253 #define memcpy_fromfs(to, from, n) \
 254 (__builtin_constant_p(n) ? \
 255  __constant_memcpy_fromfs((to),(from),(n)) : \
 256  __generic_memcpy_fromfs((to),(from),(n)))
 257 
 258 #define memcpy_tofs(to, from, n) \
 259 (__builtin_constant_p(n) ? \
 260  __constant_memcpy_tofs((to),(from),(n)) : \
 261  __generic_memcpy_tofs((to),(from),(n)))
 262 
 263 /*
 264  * These are deprecated..
 265  *
 266  * Use "put_user()" and "get_user()" with the proper pointer types instead.
 267  */
 268 
 269 #define get_fs_byte(addr) __get_user((const unsigned char *)(addr),1)
 270 #define get_fs_word(addr) __get_user((const unsigned short *)(addr),2)
 271 #define get_fs_long(addr) __get_user((const unsigned int *)(addr),4)
 272 
 273 #define put_fs_byte(x,addr) __put_user((x),(unsigned char *)(addr),1)
 274 #define put_fs_word(x,addr) __put_user((x),(unsigned short *)(addr),2)
 275 #define put_fs_long(x,addr) __put_user((x),(unsigned int *)(addr),4)
 276 
 277 #ifdef WE_REALLY_WANT_TO_USE_A_BROKEN_INTERFACE
 278 
 279 static inline unsigned short get_user_word(const short *addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 280 {
 281         return __get_user(addr, 2);
 282 }
 283 
 284 static inline unsigned char get_user_byte(const char * addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 285 {
 286         return __get_user(addr,1);
 287 }
 288 
 289 static inline unsigned long get_user_long(const int *addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 290 {
 291         return __get_user(addr, 4);
 292 }
 293 
 294 static inline void put_user_byte(char val,char *addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 295 {
 296         __put_user(val, addr, 1);
 297 }
 298 
 299 static inline void put_user_word(short val,short * addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 300 {
 301         __put_user(val, addr, 2);
 302 }
 303 
 304 static inline void put_user_long(unsigned long val,int * addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 305 {
 306         __put_user(val, addr, 4);
 307 }
 308 
 309 #endif
 310 
 311 /*
 312  * Someone who knows GNU asm better than I should double check the following.
 313  * It seems to work, but I don't know if I'm doing something subtly wrong.
 314  * --- TYT, 11/24/91
 315  * [ nothing wrong here, Linus: I just changed the ax to be any reg ]
 316  */
 317 
 318 static inline unsigned long get_fs(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 319 {
 320         unsigned long _v;
 321         __asm__("mov %%fs,%w0":"=r" (_v):"0" (0));
 322         return _v;
 323 }
 324 
 325 static inline unsigned long get_ds(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 326 {
 327         unsigned long _v;
 328         __asm__("mov %%ds,%w0":"=r" (_v):"0" (0));
 329         return _v;
 330 }
 331 
 332 static inline void set_fs(unsigned long val)
     /* [previous][next][first][last][top][bottom][index][help] */
 333 {
 334         __asm__ __volatile__("mov %w0,%%fs": /* no output */ :"r" (val));
 335 }
 336 
 337 #endif /* __ASSEMBLY__ */
 338 
 339 #endif /* _ASM_SEGMENT_H */

/* [previous][next][first][last][top][bottom][index][help] */