|
|
1.1 ! root 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) ! 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) ! 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) ! 84: { ! 85: __asm__ volatile ! 86: (" cld ! 87: push %%es ! 88: push %%fs ! 89: cmpl $3,%0 ! 90: pop %%es ! 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) ! 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) ! 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) ! 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) ! 280: { ! 281: return __get_user(addr, 2); ! 282: } ! 283: ! 284: static inline unsigned char get_user_byte(const char * addr) ! 285: { ! 286: return __get_user(addr,1); ! 287: } ! 288: ! 289: static inline unsigned long get_user_long(const int *addr) ! 290: { ! 291: return __get_user(addr, 4); ! 292: } ! 293: ! 294: static inline void put_user_byte(char val,char *addr) ! 295: { ! 296: __put_user(val, addr, 1); ! 297: } ! 298: ! 299: static inline void put_user_word(short val,short * addr) ! 300: { ! 301: __put_user(val, addr, 2); ! 302: } ! 303: ! 304: static inline void put_user_long(unsigned long val,int * addr) ! 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) ! 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) ! 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) ! 333: { ! 334: __asm__ __volatile__("mov %w0,%%fs": /* no output */ :"r" (val)); ! 335: } ! 336: ! 337: #endif /* __ASSEMBLY__ */ ! 338: ! 339: #endif /* _ASM_SEGMENT_H */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.