diff options
author | Michal Simek <monstr@monstr.eu> | 2010-03-08 04:52:24 -0500 |
---|---|---|
committer | Michal Simek <monstr@monstr.eu> | 2010-04-01 02:38:22 -0400 |
commit | 3a6d77245efe062993284fd1c2f7510d9a90efe1 (patch) | |
tree | 8ac06ff35d012d905fc82c38af5f6ab42cd43eb9 /arch/microblaze | |
parent | 527bdb52d50ddbc8dd64369e464d7a08bc7eb83c (diff) |
microblaze: uaccess: Fix get_user macro for noMMU
Use unified version.
Signed-off-by: Michal Simek <monstr@monstr.eu>
Diffstat (limited to 'arch/microblaze')
-rw-r--r-- | arch/microblaze/include/asm/uaccess.h | 89 |
1 files changed, 66 insertions, 23 deletions
diff --git a/arch/microblaze/include/asm/uaccess.h b/arch/microblaze/include/asm/uaccess.h index 1af92025fff9..b079ac31a671 100644 --- a/arch/microblaze/include/asm/uaccess.h +++ b/arch/microblaze/include/asm/uaccess.h | |||
@@ -146,31 +146,75 @@ static inline unsigned long __must_check clear_user(void __user *to, | |||
146 | 146 | ||
147 | #ifndef CONFIG_MMU | 147 | #ifndef CONFIG_MMU |
148 | 148 | ||
149 | /* Undefined function to trigger linker error */ | 149 | extern long __user_bad(void); |
150 | extern int bad_user_access_length(void); | 150 | |
151 | #define __get_user_asm(insn, __gu_ptr, __gu_val, __gu_err) \ | ||
152 | ({ \ | ||
153 | __asm__ __volatile__ ( \ | ||
154 | "1:" insn " %1, %2, r0;" \ | ||
155 | " addk %0, r0, r0;" \ | ||
156 | "2: " \ | ||
157 | __FIXUP_SECTION \ | ||
158 | "3: brid 2b;" \ | ||
159 | " addik %0, r0, %3;" \ | ||
160 | ".previous;" \ | ||
161 | __EX_TABLE_SECTION \ | ||
162 | ".word 1b,3b;" \ | ||
163 | ".previous;" \ | ||
164 | : "=&r"(__gu_err), "=r"(__gu_val) \ | ||
165 | : "r"(__gu_ptr), "i"(-EFAULT) \ | ||
166 | ); \ | ||
167 | }) | ||
168 | |||
169 | /** | ||
170 | * get_user: - Get a simple variable from user space. | ||
171 | * @x: Variable to store result. | ||
172 | * @ptr: Source address, in user space. | ||
173 | * | ||
174 | * Context: User context only. This function may sleep. | ||
175 | * | ||
176 | * This macro copies a single simple variable from user space to kernel | ||
177 | * space. It supports simple types like char and int, but not larger | ||
178 | * data types like structures or arrays. | ||
179 | * | ||
180 | * @ptr must have pointer-to-simple-variable type, and the result of | ||
181 | * dereferencing @ptr must be assignable to @x without a cast. | ||
182 | * | ||
183 | * Returns zero on success, or -EFAULT on error. | ||
184 | * On error, the variable @x is set to zero. | ||
185 | */ | ||
186 | |||
187 | #define __get_user(x, ptr) \ | ||
188 | ({ \ | ||
189 | unsigned long __gu_val; \ | ||
190 | /*unsigned long __gu_ptr = (unsigned long)(ptr);*/ \ | ||
191 | long __gu_err; \ | ||
192 | switch (sizeof(*(ptr))) { \ | ||
193 | case 1: \ | ||
194 | __get_user_asm("lbu", (ptr), __gu_val, __gu_err); \ | ||
195 | break; \ | ||
196 | case 2: \ | ||
197 | __get_user_asm("lhu", (ptr), __gu_val, __gu_err); \ | ||
198 | break; \ | ||
199 | case 4: \ | ||
200 | __get_user_asm("lw", (ptr), __gu_val, __gu_err); \ | ||
201 | break; \ | ||
202 | default: \ | ||
203 | /* __gu_val = 0; __gu_err = -EINVAL;*/ __gu_err = __user_bad();\ | ||
204 | } \ | ||
205 | x = (__typeof__(*(ptr))) __gu_val; \ | ||
206 | __gu_err; \ | ||
207 | }) | ||
208 | |||
151 | 209 | ||
152 | /* FIXME this is function for optimalization -> memcpy */ | 210 | #define get_user(x, ptr) \ |
153 | #define __get_user(var, ptr) \ | 211 | ({ \ |
154 | ({ \ | 212 | access_ok(VERIFY_READ, (ptr), sizeof(*(ptr))) \ |
155 | int __gu_err = 0; \ | 213 | ? __get_user((x), (ptr)) : -EFAULT; \ |
156 | switch (sizeof(*(ptr))) { \ | ||
157 | case 1: \ | ||
158 | case 2: \ | ||
159 | case 4: \ | ||
160 | (var) = *(ptr); \ | ||
161 | break; \ | ||
162 | case 8: \ | ||
163 | memcpy((void *) &(var), (ptr), 8); \ | ||
164 | break; \ | ||
165 | default: \ | ||
166 | (var) = 0; \ | ||
167 | __gu_err = __get_user_bad(); \ | ||
168 | break; \ | ||
169 | } \ | ||
170 | __gu_err; \ | ||
171 | }) | 214 | }) |
172 | 215 | ||
173 | #define __get_user_bad() (bad_user_access_length(), (-EFAULT)) | 216 | /* Undefined function to trigger linker error */ |
217 | extern int bad_user_access_length(void); | ||
174 | 218 | ||
175 | /* FIXME is not there defined __pu_val */ | 219 | /* FIXME is not there defined __pu_val */ |
176 | #define __put_user(var, ptr) \ | 220 | #define __put_user(var, ptr) \ |
@@ -197,7 +241,6 @@ extern int bad_user_access_length(void); | |||
197 | #define __put_user_bad() (bad_user_access_length(), (-EFAULT)) | 241 | #define __put_user_bad() (bad_user_access_length(), (-EFAULT)) |
198 | 242 | ||
199 | #define put_user(x, ptr) __put_user((x), (ptr)) | 243 | #define put_user(x, ptr) __put_user((x), (ptr)) |
200 | #define get_user(x, ptr) __get_user((x), (ptr)) | ||
201 | 244 | ||
202 | #define copy_to_user(to, from, n) (memcpy((to), (from), (n)), 0) | 245 | #define copy_to_user(to, from, n) (memcpy((to), (from), (n)), 0) |
203 | #define copy_from_user(to, from, n) (memcpy((to), (from), (n)), 0) | 246 | #define copy_from_user(to, from, n) (memcpy((to), (from), (n)), 0) |