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. get_user_byte
  4. get_user_word
  5. get_user_long
  6. put_user_byte
  7. put_user_word
  8. put_user_long
  9. __generic_memcpy_tofs
  10. __constant_memcpy_tofs
  11. __generic_memcpy_fromfs
  12. __constant_memcpy_fromfs
  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 /*
  84  * These are depracated..
  85  */
  86 
  87 static inline unsigned char get_user_byte(const char * addr)
     /* [previous][next][first][last][top][bottom][index][help] */
  88 {
  89         return __get_user(addr,1);
  90 }
  91 
  92 #define get_fs_byte(addr) get_user_byte((char *)(addr))
  93 
  94 static inline unsigned short get_user_word(const short *addr)
     /* [previous][next][first][last][top][bottom][index][help] */
  95 {
  96         return __get_user(addr, 2);
  97 }
  98 
  99 #define get_fs_word(addr) get_user_word((short *)(addr))
 100 
 101 static inline unsigned long get_user_long(const int *addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 102 {
 103         return __get_user(addr, 4);
 104 }
 105 
 106 #define get_fs_long(addr) get_user_long((int *)(addr))
 107 
 108 static inline void put_user_byte(char val,char *addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 109 {
 110         __put_user(val, addr, 1);
 111 }
 112 
 113 #define put_fs_byte(x,addr) put_user_byte((x),(char *)(addr))
 114 
 115 static inline void put_user_word(short val,short * addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 116 {
 117         __put_user(val, addr, 2);
 118 }
 119 
 120 #define put_fs_word(x,addr) put_user_word((x),(short *)(addr))
 121 
 122 static inline void put_user_long(unsigned long val,int * addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 123 {
 124         __put_user(val, addr, 4);
 125 }
 126 
 127 #define put_fs_long(x,addr) put_user_long((x),(int *)(addr))
 128 
 129 static inline void __generic_memcpy_tofs(void * to, const void * from, unsigned long n)
     /* [previous][next][first][last][top][bottom][index][help] */
 130 {
 131     __asm__ volatile
 132         ("      cld
 133                 push %%es
 134                 movw %%fs,%%cx
 135                 movw %%cx,%%es
 136                 cmpl $3,%0
 137                 jbe 1f
 138                 movl %%edi,%%ecx
 139                 negl %%ecx
 140                 andl $3,%%ecx
 141                 subl %%ecx,%0
 142                 rep; movsb
 143                 movl %0,%%ecx
 144                 shrl $2,%%ecx
 145                 rep; movsl
 146                 andl $3,%0
 147         1:      movl %0,%%ecx
 148                 rep; movsb
 149                 pop %%es"
 150         :"=abd" (n)
 151         :"0" (n),"D" ((long) to),"S" ((long) from)
 152         :"cx","di","si");
 153 }
 154 
 155 static inline void __constant_memcpy_tofs(void * to, const void * from, unsigned long n)
     /* [previous][next][first][last][top][bottom][index][help] */
 156 {
 157         switch (n) {
 158                 case 0:
 159                         return;
 160                 case 1:
 161                         __put_user(*(const char *) from, (char *) to, 1);
 162                         return;
 163                 case 2:
 164                         __put_user(*(const short *) from, (short *) to, 2);
 165                         return;
 166                 case 3:
 167                         __put_user(*(const short *) from, (short *) to, 2);
 168                         __put_user(*(2+(const char *) from), 2+(char *) to, 1);
 169                         return;
 170                 case 4:
 171                         __put_user(*(const int *) from, (int *) to, 4);
 172                         return;
 173                 case 8:
 174                         __put_user(*(const int *) from, (int *) to, 4);
 175                         __put_user(*(1+(const int *) from), 1+(int *) to, 4);
 176                         return;
 177                 case 12:
 178                         __put_user(*(const int *) from, (int *) to, 4);
 179                         __put_user(*(1+(const int *) from), 1+(int *) to, 4);
 180                         __put_user(*(2+(const int *) from), 2+(int *) to, 4);
 181                         return;
 182                 case 16:
 183                         __put_user(*(const int *) from, (int *) to, 4);
 184                         __put_user(*(1+(const int *) from), 1+(int *) to, 4);
 185                         __put_user(*(2+(const int *) from), 2+(int *) to, 4);
 186                         __put_user(*(3+(const int *) from), 3+(int *) to, 4);
 187                         return;
 188         }
 189 #define COMMON(x) \
 190 __asm__("cld\n\t" \
 191         "push %%es\n\t" \
 192         "push %%fs\n\t" \
 193         "pop %%es\n\t" \
 194         "rep ; movsl\n\t" \
 195         x \
 196         "pop %%es" \
 197         : /* no outputs */ \
 198         :"c" (n/4),"D" ((long) to),"S" ((long) from) \
 199         :"cx","di","si")
 200 
 201         switch (n % 4) {
 202                 case 0:
 203                         COMMON("");
 204                         return;
 205                 case 1:
 206                         COMMON("movsb\n\t");
 207                         return;
 208                 case 2:
 209                         COMMON("movsw\n\t");
 210                         return;
 211                 case 3:
 212                         COMMON("movsw\n\tmovsb\n\t");
 213                         return;
 214         }
 215 #undef COMMON
 216 }
 217 
 218 static inline void __generic_memcpy_fromfs(void * to, const void * from, unsigned long n)
     /* [previous][next][first][last][top][bottom][index][help] */
 219 {
 220     __asm__ volatile
 221         ("      cld
 222                 cmpl $3,%0
 223                 jbe 1f
 224                 movl %%edi,%%ecx
 225                 negl %%ecx
 226                 andl $3,%%ecx
 227                 subl %%ecx,%0
 228                 fs; rep; movsb
 229                 movl %0,%%ecx
 230                 shrl $2,%%ecx
 231                 fs; rep; movsl
 232                 andl $3,%0
 233         1:      movl %0,%%ecx
 234                 fs; rep; movsb"
 235         :"=abd" (n)
 236         :"0" (n),"D" ((long) to),"S" ((long) from)
 237         :"cx","di","si", "memory");
 238 }
 239 
 240 static inline void __constant_memcpy_fromfs(void * to, const void * from, unsigned long n)
     /* [previous][next][first][last][top][bottom][index][help] */
 241 {
 242         switch (n) {
 243                 case 0:
 244                         return;
 245                 case 1:
 246                         *(char *)to = __get_user((const char *) from, 1);
 247                         return;
 248                 case 2:
 249                         *(short *)to = __get_user((const short *) from, 2);
 250                         return;
 251                 case 3:
 252                         *(short *) to = __get_user((const short *) from, 2);
 253                         *((char *) to + 2) = __get_user(2+(const char *) from, 1);
 254                         return;
 255                 case 4:
 256                         *(int *) to = __get_user((const int *) from, 4);
 257                         return;
 258                 case 8:
 259                         *(int *) to = __get_user((const int *) from, 4);
 260                         *(1+(int *) to) = __get_user(1+(const int *) from, 4);
 261                         return;
 262                 case 12:
 263                         *(int *) to = __get_user((const int *) from, 4);
 264                         *(1+(int *) to) = __get_user(1+(const int *) from, 4);
 265                         *(2+(int *) to) = __get_user(2+(const int *) from, 4);
 266                         return;
 267                 case 16:
 268                         *(int *) to = __get_user((const int *) from, 4);
 269                         *(1+(int *) to) = __get_user(1+(const int *) from, 4);
 270                         *(2+(int *) to) = __get_user(2+(const int *) from, 4);
 271                         *(3+(int *) to) = __get_user(3+(const int *) from, 4);
 272                         return;
 273         }
 274 #define COMMON(x) \
 275 __asm__("cld\n\t" \
 276         "rep ; fs ; movsl\n\t" \
 277         x \
 278         : /* no outputs */ \
 279         :"c" (n/4),"D" ((long) to),"S" ((long) from) \
 280         :"cx","di","si","memory")
 281 
 282         switch (n % 4) {
 283                 case 0:
 284                         COMMON("");
 285                         return;
 286                 case 1:
 287                         COMMON("fs ; movsb");
 288                         return;
 289                 case 2:
 290                         COMMON("fs ; movsw");
 291                         return;
 292                 case 3:
 293                         COMMON("fs ; movsw\n\tfs ; movsb");
 294                         return;
 295         }
 296 #undef COMMON
 297 }
 298 
 299 #define memcpy_fromfs(to, from, n) \
 300 (__builtin_constant_p(n) ? \
 301  __constant_memcpy_fromfs((to),(from),(n)) : \
 302  __generic_memcpy_fromfs((to),(from),(n)))
 303 
 304 #define memcpy_tofs(to, from, n) \
 305 (__builtin_constant_p(n) ? \
 306  __constant_memcpy_tofs((to),(from),(n)) : \
 307  __generic_memcpy_tofs((to),(from),(n)))
 308 
 309 /*
 310  * Someone who knows GNU asm better than I should double check the following.
 311  * It seems to work, but I don't know if I'm doing something subtly wrong.
 312  * --- TYT, 11/24/91
 313  * [ nothing wrong here, Linus: I just changed the ax to be any reg ]
 314  */
 315 
 316 static inline unsigned long get_fs(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 317 {
 318         unsigned long _v;
 319         __asm__("mov %%fs,%w0":"=r" (_v):"0" (0));
 320         return _v;
 321 }
 322 
 323 static inline unsigned long get_ds(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 324 {
 325         unsigned long _v;
 326         __asm__("mov %%ds,%w0":"=r" (_v):"0" (0));
 327         return _v;
 328 }
 329 
 330 static inline void set_fs(unsigned long val)
     /* [previous][next][first][last][top][bottom][index][help] */
 331 {
 332         __asm__ __volatile__("mov %w0,%%fs": /* no output */ :"r" (val));
 333 }
 334 
 335 #endif /* __ASSEMBLY__ */
 336 
 337 #endif /* _ASM_SEGMENT_H */

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