|
|
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.