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

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