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