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