|
|
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:
1.1.1.2 ! root 95: #if defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 95)
1.1 root 96: static inline void __generic_memcpy_tofs(void * to, const void * from, unsigned long n)
97: {
98: __asm__ volatile
99: (" cld
100: push %%es
101: push %%fs
102: cmpl $3,%0
103: pop %%es
104: jbe 1f
105: movl %%edi,%%ecx
106: negl %%ecx
107: andl $3,%%ecx
108: subl %%ecx,%0
109: rep; movsb
110: movl %0,%%ecx
111: shrl $2,%%ecx
112: rep; movsl
113: andl $3,%0
114: 1: movl %0,%%ecx
115: rep; movsb
116: pop %%es"
117: :"=abd" (n)
118: :"0" (n),"D" ((long) to),"S" ((long) from)
119: :"cx","di","si");
120: }
121:
122: static inline void __constant_memcpy_tofs(void * to, const void * from, unsigned long n)
123: {
124: switch (n) {
125: case 0:
126: return;
127: case 1:
128: __put_user(*(const char *) from, (char *) to, 1);
129: return;
130: case 2:
131: __put_user(*(const short *) from, (short *) to, 2);
132: return;
133: case 3:
134: __put_user(*(const short *) from, (short *) to, 2);
135: __put_user(*(2+(const char *) from), 2+(char *) to, 1);
136: return;
137: case 4:
138: __put_user(*(const int *) from, (int *) to, 4);
139: return;
140: case 8:
141: __put_user(*(const int *) from, (int *) to, 4);
142: __put_user(*(1+(const int *) from), 1+(int *) to, 4);
143: return;
144: case 12:
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: return;
149: case 16:
150: __put_user(*(const int *) from, (int *) to, 4);
151: __put_user(*(1+(const int *) from), 1+(int *) to, 4);
152: __put_user(*(2+(const int *) from), 2+(int *) to, 4);
153: __put_user(*(3+(const int *) from), 3+(int *) to, 4);
154: return;
155: }
156: #define COMMON(x) \
157: __asm__("cld\n\t" \
158: "push %%es\n\t" \
159: "push %%fs\n\t" \
160: "pop %%es\n\t" \
161: "rep ; movsl\n\t" \
162: x \
163: "pop %%es" \
164: : /* no outputs */ \
165: :"c" (n/4),"D" ((long) to),"S" ((long) from) \
166: :"cx","di","si")
167:
168: switch (n % 4) {
169: case 0:
170: COMMON("");
171: return;
172: case 1:
173: COMMON("movsb\n\t");
174: return;
175: case 2:
176: COMMON("movsw\n\t");
177: return;
178: case 3:
179: COMMON("movsw\n\tmovsb\n\t");
180: return;
181: }
182: #undef COMMON
183: }
184:
185: static inline void __generic_memcpy_fromfs(void * to, const void * from, unsigned long n)
186: {
187: __asm__ volatile
188: (" cld
189: cmpl $3,%0
190: jbe 1f
191: movl %%edi,%%ecx
192: negl %%ecx
193: andl $3,%%ecx
194: subl %%ecx,%0
195: fs; rep; movsb
196: movl %0,%%ecx
197: shrl $2,%%ecx
198: fs; rep; movsl
199: andl $3,%0
200: 1: movl %0,%%ecx
201: fs; rep; movsb"
202: :"=abd" (n)
203: :"0" (n),"D" ((long) to),"S" ((long) from)
204: :"cx","di","si", "memory");
205: }
206:
207: static inline void __constant_memcpy_fromfs(void * to, const void * from, unsigned long n)
208: {
209: switch (n) {
210: case 0:
211: return;
212: case 1:
213: *(char *)to = __get_user((const char *) from, 1);
214: return;
215: case 2:
216: *(short *)to = __get_user((const short *) from, 2);
217: return;
218: case 3:
219: *(short *) to = __get_user((const short *) from, 2);
220: *((char *) to + 2) = __get_user(2+(const char *) from, 1);
221: return;
222: case 4:
223: *(int *) to = __get_user((const int *) from, 4);
224: return;
225: case 8:
226: *(int *) to = __get_user((const int *) from, 4);
227: *(1+(int *) to) = __get_user(1+(const int *) from, 4);
228: return;
229: case 12:
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: return;
234: case 16:
235: *(int *) to = __get_user((const int *) from, 4);
236: *(1+(int *) to) = __get_user(1+(const int *) from, 4);
237: *(2+(int *) to) = __get_user(2+(const int *) from, 4);
238: *(3+(int *) to) = __get_user(3+(const int *) from, 4);
239: return;
240: }
241: #define COMMON(x) \
242: __asm__("cld\n\t" \
243: "rep ; fs ; movsl\n\t" \
244: x \
245: : /* no outputs */ \
246: :"c" (n/4),"D" ((long) to),"S" ((long) from) \
247: :"cx","di","si","memory")
248:
249: switch (n % 4) {
250: case 0:
251: COMMON("");
252: return;
253: case 1:
254: COMMON("fs ; movsb");
255: return;
256: case 2:
257: COMMON("fs ; movsw");
258: return;
259: case 3:
260: COMMON("fs ; movsw\n\tfs ; movsb");
261: return;
262: }
263: #undef COMMON
264: }
265:
266: #define memcpy_fromfs(to, from, n) \
267: (__builtin_constant_p(n) ? \
268: __constant_memcpy_fromfs((to),(from),(n)) : \
269: __generic_memcpy_fromfs((to),(from),(n)))
270:
271: #define memcpy_tofs(to, from, n) \
272: (__builtin_constant_p(n) ? \
273: __constant_memcpy_tofs((to),(from),(n)) : \
274: __generic_memcpy_tofs((to),(from),(n)))
275:
1.1.1.2 ! root 276:
! 277: #else /* code for gcc-2.95.x and newer follows */
! 278:
! 279: static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
! 280: {
! 281: char *d = (char *)to;
! 282: const char *s = (const char *)from;
! 283: while (n-- > 0) {
! 284: *d++ = __get_user(s++, 1);
! 285: }
! 286: }
! 287:
! 288: static inline void memcpy_tofs(void * to, const void * from, unsigned long n)
! 289: {
! 290: char *d = (char *)to;
! 291: const char *s = (const char *)from;
! 292: while (n-- > 0) {
! 293: __put_user(*s++, d++, 1);
! 294: }
! 295: }
! 296:
! 297: #endif /* not gcc-2.95 */
! 298:
1.1 root 299: /*
300: * These are deprecated..
301: *
302: * Use "put_user()" and "get_user()" with the proper pointer types instead.
303: */
304:
305: #define get_fs_byte(addr) __get_user((const unsigned char *)(addr),1)
306: #define get_fs_word(addr) __get_user((const unsigned short *)(addr),2)
307: #define get_fs_long(addr) __get_user((const unsigned int *)(addr),4)
308:
309: #define put_fs_byte(x,addr) __put_user((x),(unsigned char *)(addr),1)
310: #define put_fs_word(x,addr) __put_user((x),(unsigned short *)(addr),2)
311: #define put_fs_long(x,addr) __put_user((x),(unsigned int *)(addr),4)
312:
313: #ifdef WE_REALLY_WANT_TO_USE_A_BROKEN_INTERFACE
314:
315: static inline unsigned short get_user_word(const short *addr)
316: {
317: return __get_user(addr, 2);
318: }
319:
320: static inline unsigned char get_user_byte(const char * addr)
321: {
322: return __get_user(addr,1);
323: }
324:
325: static inline unsigned long get_user_long(const int *addr)
326: {
327: return __get_user(addr, 4);
328: }
329:
330: static inline void put_user_byte(char val,char *addr)
331: {
332: __put_user(val, addr, 1);
333: }
334:
335: static inline void put_user_word(short val,short * addr)
336: {
337: __put_user(val, addr, 2);
338: }
339:
340: static inline void put_user_long(unsigned long val,int * addr)
341: {
342: __put_user(val, addr, 4);
343: }
344:
345: #endif
346:
347: /*
348: * Someone who knows GNU asm better than I should double check the following.
349: * It seems to work, but I don't know if I'm doing something subtly wrong.
350: * --- TYT, 11/24/91
351: * [ nothing wrong here, Linus: I just changed the ax to be any reg ]
352: */
353:
354: static inline unsigned long get_fs(void)
355: {
356: unsigned long _v;
357: __asm__("mov %%fs,%w0":"=r" (_v):"0" (0));
358: return _v;
359: }
360:
361: static inline unsigned long get_ds(void)
362: {
363: unsigned long _v;
364: __asm__("mov %%ds,%w0":"=r" (_v):"0" (0));
365: return _v;
366: }
367:
368: static inline void set_fs(unsigned long val)
369: {
370: __asm__ __volatile__("mov %w0,%%fs": /* no output */ :"r" (val));
371: }
372:
373: #endif /* __ASSEMBLY__ */
374:
375: #endif /* _ASM_SEGMENT_H */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.