1 #ifndef_ASM_SEGMENT_H 2 #define_ASM_SEGMENT_H 3
4 #include <linux/string.h>
5
6 /* 7 * This is a gcc optimization barrier, which essentially 8 * inserts a sequence point in the gcc RTL tree that gcc 9 * can't move code around. This is needed when we enter 10 * or exit a critical region (in this case around user-level 11 * accesses that may sleep, and we can't let gcc optimize 12 * global state around them). 13 */ 14 #define__gcc_barrier() __asm____volatile__("": : :"memory")
15
16 /* 17 * Uh, these should become the main single-value transfer routines.. 18 * They automatically use the right size if we just have the right 19 * pointer type.. 20 */ 21 #defineput_user(x,ptr) __put_user((unsignedlong)(x),(ptr),sizeof(*(ptr)))
22 #defineget_user(ptr) ((__typeof__(*(ptr)))__get_user((ptr),sizeof(*(ptr))))
23
24 /* 25 * This is a silly but good way to make sure that 26 * the __put_user function is indeed always optimized, 27 * and that we use the correct sizes.. 28 */ 29 externintbad_user_access_length(void);
30
31 /* I should make this use unaligned transfers etc.. */ 32 staticinlinevoid__put_user(unsignedlongx, void * y, intsize)
/* */ 33 { 34 __gcc_barrier();
35 switch (size) { 36 case 1:
37 *(char *) y = x;
38 break;
39 case 2:
40 *(short *) y = x;
41 break;
42 case 4:
43 *(int *) y = x;
44 break;
45 case 8:
46 *(long *) y = x;
47 break;
48 default:
49 bad_user_access_length();
50 } 51 __gcc_barrier();
52 } 53
54 /* I should make this use unaligned transfers etc.. */ 55 staticinlineunsignedlong__get_user(constvoid * y, intsize)
/* */ 56 { 57 unsignedlongresult;
58
59 __gcc_barrier();
60 switch (size) { 61 case 1:
62 result = *(unsignedchar *) y;
63 break;
64 case 2:
65 result = *(unsignedshort *) y;
66 break;
67 case 4:
68 result = *(unsignedint *) y;
69 break;
70 case 8:
71 result = *(unsignedlong *) y;
72 break;
73 default:
74 result = bad_user_access_length();
75 } 76 __gcc_barrier();
77 returnresult;
78 } 79
80 #defineget_fs_byte(addr) get_user((unsignedchar *)(addr))
81 #defineget_fs_word(addr) get_user((unsignedshort *)(addr))
82 #defineget_fs_long(addr) get_user((unsignedint *)(addr))
83 #defineget_fs_quad(addr) get_user((unsignedlong *)(addr))
84
85 #defineput_fs_byte(x,addr) put_user((x),(char *)(addr))
86 #defineput_fs_word(x,addr) put_user((x),(short *)(addr))
87 #defineput_fs_long(x,addr) put_user((x),(int *)(addr))
88 #defineput_fs_quad(x,addr) put_user((x),(long *)(addr))
89
90 staticinlinevoidmemcpy_fromfs(void * to, constvoid * from, unsignedlongn)
/* */ 91 { 92 __gcc_barrier();
93 memcpy(to, from, n);
94 __gcc_barrier();
95 } 96
97 staticinlinevoidmemcpy_tofs(void * to, constvoid * from, unsignedlongn)
/* */ 98 { 99 __gcc_barrier();
100 memcpy(to, from, n);
101 __gcc_barrier();
102 } 103
104 /* 105 * For segmented architectures, these are used to specify which segment 106 * to use for the above functions. 107 * 108 * The alpha is not segmented, so these are just dummies. 109 */ 110
111 #defineKERNEL_DS 0
112 #defineUSER_DS 1
113
114 staticinlineunsignedlongget_fs(void)
/* */ 115 { 116 return 1;
117 } 118
119 staticinlineunsignedlongget_ds(void)
/* */ 120 { 121 return 0;
122 } 123
124 staticinlinevoidset_fs(unsignedlongval)
/* */ 125 { 126 } 127
128 #endif/* _ASM_SEGMENT_H */