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