~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/include/asm-s390/uaccess.h

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  include/asm-s390/uaccess.h
  3  *
  4  *  S390 version
  5  *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  6  *    Author(s): Hartmut Penner (hp@de.ibm.com),
  7  *               Martin Schwidefsky (schwidefsky@de.ibm.com)
  8  *
  9  *  Derived from "include/asm-i386/uaccess.h"
 10  */
 11 #ifndef __S390_UACCESS_H
 12 #define __S390_UACCESS_H
 13 
 14 /*
 15  * User space memory access functions
 16  */
 17 #include <linux/sched.h>
 18 #if 0
 19 #include <asm/segment.h>
 20 #endif
 21 #define VERIFY_READ     0
 22 #define VERIFY_WRITE    1
 23 
 24 
 25 /*
 26  * The fs value determines whether argument validity checking should be
 27  * performed or not.  If get_fs() == USER_DS, checking is performed, with
 28  * get_fs() == KERNEL_DS, checking is bypassed.
 29  *
 30  * For historical reasons, these macros are grossly misnamed.
 31  */
 32 
 33 #define MAKE_MM_SEG(s,a)  ((mm_segment_t) { (s),(a) })
 34 
 35 
 36 #define KERNEL_DS       MAKE_MM_SEG(0x7FFFFFFF,0)
 37 #define USER_DS         MAKE_MM_SEG(PAGE_OFFSET,1)
 38 
 39 #define get_ds()        (KERNEL_DS)
 40 #define get_fs()        (current->thread.fs)
 41 #define set_fs(x)       ({asm volatile("sar   4,%0"::"a" (x.acc4)); \
 42                          current->thread.fs = (x);})
 43 
 44 #define segment_eq(a,b) ((a).acc4 == (b).acc4)
 45 
 46 
 47 #define __access_ok(addr,size) ((((long) addr + size)&0x7FFFFFFFL) < current->addr_limit.seg)
 48 
 49 #define access_ok(type,addr,size) __access_ok(addr,size)
 50 
 51 extern inline int verify_area(int type, const void * addr, unsigned long size)
 52 {
 53         return access_ok(type,addr,size)?0:-EFAULT;
 54 }
 55 
 56 /*
 57  * The exception table consists of pairs of addresses: the first is the
 58  * address of an instruction that is allowed to fault, and the second is
 59  * the address at which the program should continue.  No registers are
 60  * modified, so it is entirely up to the continuation code to figure out
 61  * what to do.
 62  *
 63  * All the routines below use bits of fixup code that are out of line
 64  * with the main instruction path.  This means when everything is well,
 65  * we don't even have to jump over them.  Further, they do not intrude
 66  * on our cache or tlb entries.
 67  */
 68 
 69 struct exception_table_entry
 70 {
 71         unsigned long insn, fixup;
 72 };
 73 
 74 /* Returns 0 if exception not found and fixup otherwise.  */
 75 extern unsigned long search_exception_table(unsigned long);
 76 
 77 
 78 /*
 79  * These are the main single-value transfer routines.  They automatically
 80  * use the right size if we just have the right pointer type.
 81  */
 82 
 83 extern inline int __put_user_asm_4(__u32 x, void *ptr)
 84 {
 85         int err;
 86 
 87         __asm__ __volatile__ (  "   iac   1\n"
 88                                 "   sr    %1,%1\n"
 89                                 "   la    4,%0\n"
 90                                 "   sacf  512\n"
 91                                 "0: st    %2,0(4)\n"
 92                                 "   sacf  0(1)\n"
 93                                 "1:\n"
 94                                 ".section .fixup,\"ax\"\n"
 95                                 "2: sacf  0(1)\n"
 96                                 "   lhi   %1,%h3\n"
 97                                 "   bras  4,3f\n"
 98                                 "   .long 1b\n"
 99                                 "3: l     4,0(4)\n"
100                                 "   br    4\n"
101                                 ".previous\n"
102                                 ".section __ex_table,\"a\"\n"
103                                 "   .align 4\n"
104                                 "   .long  0b,2b\n"
105                                 ".previous"
106                                 : "=m" (*((__u32*) ptr)) , "=&d" (err)
107                                 : "d" (x), "K" (-EFAULT)
108                                 : "1", "4" );
109         return err;
110 }
111 
112 extern inline int __put_user_asm_2(__u16 x, void *ptr)
113 {
114         int err;
115 
116         __asm__ __volatile__ (  "   iac   1\n"
117                                 "   sr    %1,%1\n"
118                                 "   la    4,%0\n"
119                                 "   sacf  512\n"
120                                 "0: sth   %2,0(4)\n"
121                                 "   sacf  0(1)\n"
122                                 "1:\n"
123                                 ".section .fixup,\"ax\"\n"
124                                 "2: sacf  0(1)\n"
125                                 "   lhi   %1,%h3\n"
126                                 "   bras  4,3f\n"
127                                 "   .long 1b\n"
128                                 "3: l     4,0(4)\n"
129                                 "   br    4\n"
130                                 ".previous\n"
131                                 ".section __ex_table,\"a\"\n"
132                                 "   .align 4\n"
133                                 "   .long  0b,2b\n"
134                                 ".previous"
135                                 : "=m" (*((__u16*) ptr)) , "=&d" (err)
136                                 : "d" (x), "K" (-EFAULT)
137                                 : "1", "4" );
138         return err;
139 }
140 
141 extern inline int __put_user_asm_1(__u8 x, void *ptr)
142 {
143         int err;
144 
145         __asm__ __volatile__ (  "   iac   1\n"
146                                 "   sr    %1,%1\n"
147                                 "   la    4,%0\n"
148                                 "   sacf  512\n"
149                                 "0: stc   %2,0(4)\n"
150                                 "   sacf  0(1)\n"
151                                 "1:\n"
152                                 ".section .fixup,\"ax\"\n"
153                                 "2: sacf  0(1)\n"
154                                 "   lhi   %1,%h3\n"
155                                 "   bras  4,3f\n"
156                                 "   .long 1b\n"
157                                 "3: l     4,0(4)\n"
158                                 "   br    4\n"
159                                 ".previous\n"
160                                 ".section __ex_table,\"a\"\n"
161                                 "   .align 4\n"
162                                 "   .long  0b,2b\n"
163                                 ".previous"
164                                 : "=m" (*((__u8*) ptr)) , "=&d" (err)
165                                 : "d" (x), "K" (-EFAULT)
166                                 : "1", "4" );
167         return err;
168 }
169 
170 /*
171  * (u8)(u32) ... autsch, but that the only way we can suppress the
172  * warnings when compiling binfmt_elf.c
173  */
174 #define __put_user(x, ptr)                                      \
175 ({                                                              \
176         int __pu_err;                                           \
177         switch (sizeof (*(ptr))) {                              \
178                 case 1:                                         \
179                         __pu_err = __put_user_asm_1((__u8)(__u32)x,ptr);\
180                         break;                                  \
181                 case 2:                                         \
182                         __pu_err = __put_user_asm_2((__u16)(__u32)x,ptr);\
183                         break;                                  \
184                 case 4:                                         \
185                         __pu_err = __put_user_asm_4((__u32) x,ptr);\
186                         break;                                  \
187                 default:                                        \
188                 __pu_err = __put_user_bad();                    \
189                 break;                                          \
190          }                                                      \
191         __pu_err;                                               \
192 })
193 
194 #define put_user(x, ptr)                                        \
195 ({                                                              \
196         long __pu_err = -EFAULT;                                \
197         __typeof__(*(ptr)) *__pu_addr = (ptr);                  \
198         __typeof__(x) __x = (x);                                \
199         if (__access_ok((long)__pu_addr,sizeof(*(ptr)))) {      \
200                 __pu_err = 0;                                   \
201                 __put_user((__x), (__pu_addr));                 \
202         }                                                       \
203         __pu_err;                                               \
204 })
205 
206 extern int __put_user_bad(void);
207 
208 
209 #define __get_user_asm_4(x, ptr, err)                                   \
210 ({                                                                      \
211         __asm__ __volatile__ (  "   iac   1\n"                          \
212                                 "   sr    %1,%1\n"                      \
213                                 "   la    4,%2\n"                       \
214                                 "   sacf  512\n"                        \
215                                 "0: l     %0,0(4)\n"                    \
216                                 "   sacf  0(1)\n"                       \
217                                 "1:\n"                                  \
218                                 ".section .fixup,\"ax\"\n"              \
219                                 "2: sacf  0(1)\n"                       \
220                                 "   lhi   %1,%h3\n"                     \
221                                 "   bras  4,3f\n"                       \
222                                 "   .long 1b\n"                         \
223                                 "3: l     4,0(4)\n"                     \
224                                 "   br    4\n"                          \
225                                 ".previous\n"                           \
226                                 ".section __ex_table,\"a\"\n"           \
227                                 "   .align 4\n"                         \
228                                 "   .long 0b,2b\n"                      \
229                                 ".previous"                             \
230                                 : "=d" (x) , "=&d" (err)                \
231                                 : "m" (*(__u32*) ptr), "K" (-EFAULT)    \
232                                 : "1", "4" );                           \
233 })
234 
235 #define __get_user_asm_2(x, ptr, err)                                   \
236 ({                                                                      \
237         __asm__ __volatile__ (  "   iac   1\n"                          \
238                                 "   sr    %1,%1\n"                      \
239                                 "   la    4,%2\n"                       \
240                                 "   sacf  512\n"                        \
241                                 "0: lh    %0,0(4)\n"                    \
242                                 "   sacf  0(1)\n"                       \
243                                 "1:\n"                                  \
244                                 ".section .fixup,\"ax\"\n"              \
245                                 "2: sacf  0(1)\n"                       \
246                                 "   lhi   %1,%h3\n"                     \
247                                 "   bras  4,3f\n"                       \
248                                 "   .long 1b\n"                         \
249                                 "3: l     4,0(4)\n"                     \
250                                 "   br    4\n"                          \
251                                 ".previous\n"                           \
252                                 ".section __ex_table,\"a\"\n"           \
253                                 "   .align 4\n"                         \
254                                 "   .long 0b,2b\n"                      \
255                                 ".previous"                             \
256                                 : "=d" (x) , "=&d" (err)                \
257                                 : "m" (*(__u16*) ptr), "K" (-EFAULT)    \
258                                 : "1", "4" );                           \
259 })
260 
261 #define __get_user_asm_1(x, ptr, err)                                   \
262 ({                                                                      \
263         __asm__ __volatile__ (  "   iac   1\n"                          \
264                                 "   sr    %1,%1\n"                      \
265                                 "   la    4,%2\n"                       \
266                                 "   sr    %0,%0\n"                      \
267                                 "   sacf  512\n"                        \
268                                 "0: ic    %0,0(4)\n"                    \
269                                 "   sacf  0(1)\n"                       \
270                                 "1:\n"                                  \
271                                 ".section .fixup,\"ax\"\n"              \
272                                 "2: sacf  0(1)\n"                       \
273                                 "   lhi   %1,%h3\n"                     \
274                                 "   bras  4,3f\n"                       \
275                                 "   .long 1b\n"                         \
276                                 "3: l     4,0(4)\n"                     \
277                                 "   br    4\n"                          \
278                                 ".previous\n"                           \
279                                 ".section __ex_table,\"a\"\n"           \
280                                 "   .align 4\n"                         \
281                                 "   .long 0b,2b\n"                      \
282                                 ".previous"                             \
283                                 : "=d" (x) , "=&d" (err)                \
284                                 : "m" (*(__u8*) ptr), "K" (-EFAULT)     \
285                                 : "1", "4" );                           \
286 })
287 
288 #define __get_user(x, ptr)                                      \
289 ({                                                              \
290         int __gu_err;                                           \
291         switch (sizeof(*(ptr))) {                               \
292                 case 1:                                         \
293                         __get_user_asm_1(x,ptr,__gu_err);       \
294                         break;                                  \
295                 case 2:                                         \
296                         __get_user_asm_2(x,ptr,__gu_err);       \
297                         break;                                  \
298                 case 4:                                         \
299                         __get_user_asm_4(x,ptr,__gu_err);       \
300                         break;                                  \
301                 default:                                        \
302                         (x) = 0;                                \
303                         __gu_err = __get_user_bad();            \
304                 break;                                          \
305         }                                                       \
306         __gu_err;                                               \
307 })
308 
309 #define get_user(x, ptr)                                        \
310 ({                                                              \
311         long __gu_err = -EFAULT;                                \
312         __typeof__(ptr) __gu_addr = (ptr);                      \
313         __typeof__(x) __x;                                      \
314         if (__access_ok((long)__gu_addr,sizeof(*(ptr)))) {      \
315                 __gu_err = 0;                                   \
316                 __get_user((__x), (__gu_addr));                 \
317                 (x) = __x;                                      \
318         }                                                       \
319         else                                                    \
320                 (x) = 0;                                        \
321         __gu_err;                                               \
322 })
323 
324 extern int __get_user_bad(void);
325 
326 /*
327  * access register are set up, that 4 points to secondary (user) , 2 to primary (kernel)
328  */
329 
330 extern inline unsigned long
331 __copy_to_user_asm(void* to, const void* from,  long n)
332 {
333 
334         __asm__ __volatile__ (  "   iac   1\n"
335                                 "   lr    2,%2\n"
336                                 "   lr    4,%1\n"
337                                 "   lr    3,%0\n"
338                                 "   lr    5,3\n"
339                                 "   sacf  512\n"
340                                 "0: mvcle 4,2,0\n"
341                                 "   jo    0b\n"
342                                 "1: sacf  0(1)\n"
343                                 "   lr    %0,3\n"
344                                 ".section __ex_table,\"a\"\n"
345                                 "   .align 4\n"
346                                 "   .long  0b,1b\n"
347                                 ".previous"
348                                 : "+&d" (n) : "d" (to), "d" (from)
349                                 : "1", "2", "3", "4", "5" );
350         return n;
351 }
352 
353 #define __copy_to_user(to, from, n)                             \
354 ({                                                              \
355         __copy_to_user_asm(to,from,n);                          \
356 })
357 
358 #define copy_to_user(to, from, n)                               \
359 ({                                                              \
360         long err = 0;                                           \
361         __typeof__(n) __n = (n);                                \
362         if (__access_ok(to,__n)) {                              \
363                 err = __copy_to_user_asm(to,from,__n);          \
364         }                                                       \
365         else                                                    \
366                 err = __n;                                      \
367         err;                                                    \
368 })
369 
370 extern inline unsigned long
371 __copy_from_user_asm(void* to, const void* from,  long n)
372 {
373         __asm__ __volatile__ (  "   iac   1\n"
374                                 "   lr    2,%1\n"
375                                 "   lr    4,%2\n"
376                                 "   lr    3,%0\n"
377                                 "   lr    5,3\n"
378                                 "   sacf  512\n"
379                                 "0: mvcle 2,4,0\n"
380                                 "   jo    0b\n"
381                                 "1: sacf  0(1)\n"
382                                 "   lr    %0,3\n"
383                                 ".section __ex_table,\"a\"\n"
384                                 "   .align 4\n"
385                                 "   .long  0b,1b\n"
386                                 ".previous"
387                                 : "+&d" (n) : "d" (to), "d" (from)
388                                 : "1", "2", "3", "4", "5" );
389         return n;
390 }
391 
392 
393 #define __copy_from_user(to, from, n)                           \
394 ({                                                              \
395         __copy_from_user_asm(to,from,n);                        \
396 })
397 
398 #define copy_from_user(to, from, n)                             \
399 ({                                                              \
400         long err = 0;                                           \
401         __typeof__(n) __n = (n);                                \
402         if (__access_ok(from,__n)) {                            \
403                 err = __copy_from_user_asm(to,from,__n);        \
404         }                                                       \
405         else                                                    \
406                 err = __n;                                      \
407         err;                                                    \
408 })
409 
410 /*
411  * Copy a null terminated string from userspace.
412  */
413 
414 static inline long
415 strncpy_from_user(char *dst, const char *src, long count)
416 {
417         int len;
418         __asm__ __volatile__ (  "   iac   1\n"
419                                 "   slr   %0,%0\n"
420                                 "   lr    2,%1\n"
421                                 "   lr    4,%2\n"
422                                 "   slr   3,3\n"
423                                 "   sacf  512\n"
424                                 "0: ic    3,0(%0,4)\n"
425                                 "1: stc   3,0(%0,2)\n"
426                                 "   ltr   3,3\n"
427                                 "   jz    2f\n"
428                                 "   ahi   %0,1\n"
429                                 "   clr   %0,%3\n"
430                                 "   jl    0b\n"
431                                 "2: sacf  0(1)\n"
432                                 ".section .fixup,\"ax\"\n"
433                                 "3: lhi   %0,%h4\n"
434                                 "   basr  3,0\n"
435                                 "   l     3,4f-.(3)\n"
436                                 "   br    3\n"
437                                 "4: .long 2b\n"
438                                 ".previous\n"
439                                 ".section __ex_table,\"a\"\n"
440                                 "   .align 4\n"
441                                 "   .long  0b,3b\n"
442                                 "   .long  1b,3b\n"
443                                 ".previous"
444                                 : "=&a" (len)
445                                 : "a" (dst), "d" (src), "d" (count),
446                                   "K" (-EFAULT)
447                                 : "1", "2", "3", "4", "memory" );
448         return len;
449 }
450 
451 /*
452  * Return the size of a string (including the ending 0)
453  *
454  * Return 0 for error
455  */
456 static inline unsigned long
457 strnlen_user(const char * src, unsigned long n)
458 {
459         __asm__ __volatile__ ("   iac   1\n"
460                               "   alr   %0,%1\n"
461                               "   slr   0,0\n"
462                               "   lr    4,%1\n"
463                               "   sacf  512\n"
464                               "0: srst  %0,4\n"
465                               "   jo    0b\n"
466                               "   slr   %0,%1\n"
467                               "   ahi   %0,1\n"
468                               "   sacf  0(1)\n"
469                               "1:\n"
470                               ".section .fixup,\"ax\"\n"
471                               "2: sacf  0(1)\n"
472                               "   slr   %0,%0\n"
473                               "   bras  4,3f\n"
474                               "   .long 1b\n"
475                               "3: l     4,0(4)\n"
476                               "   br    4\n"
477                               ".previous\n"
478                               ".section __ex_table,\"a\"\n"
479                               "   .align 4\n"
480                               "   .long  0b,2b\n"
481                               ".previous"
482                               : "+&a" (n) : "d" (src)
483                               : "cc", "", "1", "4" );
484         return n;
485 }
486 #define strlen_user(str) strnlen_user(str, ~0UL)
487 
488 /*
489  * Zero Userspace
490  */
491 
492 static inline unsigned long
493 clear_user(void *to, unsigned long n)
494 {
495         __asm__ __volatile__ (  "   iac   1\n"
496                                 "   sacf  512\n"
497                                 "   lr    4,%1\n"
498                                 "   lr    5,%0\n"
499                                 "   sr    2,2\n"
500                                 "   sr    3,3\n"
501                                 "0: mvcle 4,2,0\n"
502                                 "   jo    0b\n"
503                                 "1: sacf  0(1)\n"
504                                 "   lr    %0,3\n"
505                                 ".section __ex_table,\"a\"\n"
506                                 "   .align 4\n"
507                                 "   .long  0b,1b\n"
508                                 ".previous"
509                                 : "+&a" (n)
510                                 : "a"   (to)
511                                 : "cc", "1", "2", "3", "4", "5" );
512         return n;
513 }
514 
515 #endif                                 /* _S390_UACCESS_H                  */
516 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.