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