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