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