2005-04-16 15:20:36 -07:00
/*
* S390 version
2012-07-20 11:15:04 +02:00
* Copyright IBM Corp . 1999 , 2000
2005-04-16 15:20:36 -07:00
* Author ( s ) : Hartmut Penner ( hp @ de . ibm . com ) ,
* Martin Schwidefsky ( schwidefsky @ de . ibm . com )
*
* Derived from " include/asm-i386/uaccess.h "
*/
# ifndef __S390_UACCESS_H
# define __S390_UACCESS_H
/*
* User space memory access functions
*/
2017-02-17 08:13:28 +01:00
# include <asm/processor.h>
2012-03-28 18:30:02 +01:00
# include <asm/ctl_reg.h>
2016-12-26 00:48:37 -05:00
# include <asm/extable.h>
2005-04-16 15:20:36 -07:00
/*
* The fs value determines whether argument validity checking should be
* performed or not . If get_fs ( ) = = USER_DS , checking is performed , with
* get_fs ( ) = = KERNEL_DS , checking is bypassed .
*
* For historical reasons , these macros are grossly misnamed .
*/
# define MAKE_MM_SEG(a) ((mm_segment_t) { (a) })
# define KERNEL_DS MAKE_MM_SEG(0)
# define USER_DS MAKE_MM_SEG(1)
# define get_ds() (KERNEL_DS)
# define get_fs() (current->thread.mm_segment)
# define segment_eq(a,b) ((a).ar4 == (b).ar4)
2017-02-17 08:13:28 +01:00
static inline void set_fs ( mm_segment_t fs )
{
current - > thread . mm_segment = fs ;
2017-03-20 21:08:07 -04:00
if ( uaccess_kernel ( ) ) {
2017-02-17 08:13:28 +01:00
set_cpu_flag ( CIF_ASCE_SECONDARY ) ;
__ctl_load ( S390_lowcore . kernel_asce , 7 , 7 ) ;
} else {
clear_cpu_flag ( CIF_ASCE_SECONDARY ) ;
__ctl_load ( S390_lowcore . user_asce , 7 , 7 ) ;
}
}
2012-05-29 07:33:59 +02:00
static inline int __range_ok ( unsigned long addr , unsigned long size )
{
return 1 ;
}
# define __access_ok(addr, size) \
( { \
__chk_user_ptr ( addr ) ; \
__range_ok ( ( unsigned long ) ( addr ) , ( size ) ) ; \
2011-05-26 09:48:25 +02:00
} )
2005-04-16 15:20:36 -07:00
2011-05-26 09:48:25 +02:00
# define access_ok(type, addr, size) __access_ok(addr, size)
2005-04-16 15:20:36 -07:00
2017-03-28 15:06:24 -04:00
unsigned long __must_check
raw_copy_from_user ( void * to , const void __user * from , unsigned long n ) ;
2012-09-05 13:26:11 +02:00
2017-03-28 15:06:24 -04:00
unsigned long __must_check
raw_copy_to_user ( void __user * to , const void * from , unsigned long n ) ;
2006-09-20 15:59:42 +02:00
2017-03-28 15:06:24 -04:00
# define INLINE_COPY_FROM_USER
# define INLINE_COPY_TO_USER
2009-12-07 12:51:47 +01:00
2014-04-17 14:16:03 +02:00
# ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
# define __put_get_user_asm(to, from, size, spec) \
( { \
register unsigned long __reg0 asm ( " 0 " ) = spec ; \
int __rc ; \
\
asm volatile ( \
" 0: mvcos %1,%3,%2 \n " \
" 1: xr %0,%0 \n " \
" 2: \n " \
" .pushsection .fixup, \" ax \" \n " \
" 3: lhi %0,%5 \n " \
" jg 2b \n " \
" .popsection \n " \
EX_TABLE ( 0 b , 3 b ) EX_TABLE ( 1 b , 3 b ) \
2017-03-27 09:48:04 +02:00
: " =d " ( __rc ) , " +Q " ( * ( to ) ) \
2014-04-17 14:16:03 +02:00
: " d " ( size ) , " Q " ( * ( from ) ) , \
" d " ( __reg0 ) , " K " ( - EFAULT ) \
: " cc " ) ; \
__rc ; \
} )
2016-06-20 10:35:20 +02:00
static inline int __put_user_fn ( void * x , void __user * ptr , unsigned long size )
{
unsigned long spec = 0x810000UL ;
int rc ;
switch ( size ) {
case 1 :
rc = __put_get_user_asm ( ( unsigned char __user * ) ptr ,
( unsigned char * ) x ,
size , spec ) ;
break ;
case 2 :
rc = __put_get_user_asm ( ( unsigned short __user * ) ptr ,
( unsigned short * ) x ,
size , spec ) ;
break ;
case 4 :
rc = __put_get_user_asm ( ( unsigned int __user * ) ptr ,
( unsigned int * ) x ,
size , spec ) ;
break ;
case 8 :
rc = __put_get_user_asm ( ( unsigned long __user * ) ptr ,
( unsigned long * ) x ,
size , spec ) ;
break ;
2017-01-02 08:51:02 +01:00
}
2016-06-20 10:35:20 +02:00
return rc ;
}
static inline int __get_user_fn ( void * x , const void __user * ptr , unsigned long size )
{
unsigned long spec = 0x81UL ;
int rc ;
switch ( size ) {
case 1 :
rc = __put_get_user_asm ( ( unsigned char * ) x ,
( unsigned char __user * ) ptr ,
size , spec ) ;
break ;
case 2 :
rc = __put_get_user_asm ( ( unsigned short * ) x ,
( unsigned short __user * ) ptr ,
size , spec ) ;
break ;
case 4 :
rc = __put_get_user_asm ( ( unsigned int * ) x ,
( unsigned int __user * ) ptr ,
size , spec ) ;
break ;
case 8 :
rc = __put_get_user_asm ( ( unsigned long * ) x ,
( unsigned long __user * ) ptr ,
size , spec ) ;
break ;
2017-01-02 08:51:02 +01:00
}
2016-06-20 10:35:20 +02:00
return rc ;
}
2014-04-17 14:16:03 +02:00
# else /* CONFIG_HAVE_MARCH_Z10_FEATURES */
2014-01-24 12:51:27 +01:00
static inline int __put_user_fn ( void * x , void __user * ptr , unsigned long size )
2006-09-20 15:59:42 +02:00
{
2017-03-28 15:06:24 -04:00
size = raw_copy_to_user ( ptr , x , size ) ;
2014-01-23 11:18:36 +01:00
return size ? - EFAULT : 0 ;
2006-09-20 15:59:42 +02:00
}
2014-01-24 12:51:27 +01:00
static inline int __get_user_fn ( void * x , const void __user * ptr , unsigned long size )
2006-09-20 15:59:42 +02:00
{
2017-03-28 15:06:24 -04:00
size = raw_copy_from_user ( x , ptr , size ) ;
2014-01-23 11:18:36 +01:00
return size ? - EFAULT : 0 ;
2006-09-20 15:59:42 +02:00
}
2005-04-16 15:20:36 -07:00
2014-04-17 14:16:03 +02:00
# endif /* CONFIG_HAVE_MARCH_Z10_FEATURES */
2005-04-16 15:20:36 -07:00
/*
* These are the main single - value transfer routines . They automatically
* use the right size if we just have the right pointer type .
*/
# define __put_user(x, ptr) \
( { \
__typeof__ ( * ( ptr ) ) __x = ( x ) ; \
2006-09-20 15:59:42 +02:00
int __pu_err = - EFAULT ; \
2005-08-23 22:48:22 +01:00
__chk_user_ptr ( ptr ) ; \
2005-04-16 15:20:36 -07:00
switch ( sizeof ( * ( ptr ) ) ) { \
case 1 : \
case 2 : \
case 4 : \
case 8 : \
2014-01-22 14:49:30 +01:00
__pu_err = __put_user_fn ( & __x , ptr , \
sizeof ( * ( ptr ) ) ) ; \
2005-04-16 15:20:36 -07:00
break ; \
default : \
__put_user_bad ( ) ; \
break ; \
} \
2016-06-13 10:17:20 +02:00
__builtin_expect ( __pu_err , 0 ) ; \
2005-04-16 15:20:36 -07:00
} )
# define put_user(x, ptr) \
( { \
2009-06-12 10:26:32 +02:00
might_fault ( ) ; \
2005-04-16 15:20:36 -07:00
__put_user ( x , ptr ) ; \
} )
2014-01-23 11:18:36 +01:00
int __put_user_bad ( void ) __attribute__ ( ( noreturn ) ) ;
2005-04-16 15:20:36 -07:00
# define __get_user(x, ptr) \
( { \
2006-09-20 15:59:42 +02:00
int __gu_err = - EFAULT ; \
__chk_user_ptr ( ptr ) ; \
2005-04-16 15:20:36 -07:00
switch ( sizeof ( * ( ptr ) ) ) { \
2005-11-07 00:59:11 -08:00
case 1 : { \
2016-08-21 22:00:54 -04:00
unsigned char __x = 0 ; \
2014-01-22 14:49:30 +01:00
__gu_err = __get_user_fn ( & __x , ptr , \
sizeof ( * ( ptr ) ) ) ; \
2006-02-03 20:11:52 -05:00
( x ) = * ( __force __typeof__ ( * ( ptr ) ) * ) & __x ; \
2005-11-07 00:59:11 -08:00
break ; \
} ; \
case 2 : { \
2016-08-21 22:00:54 -04:00
unsigned short __x = 0 ; \
2014-01-22 14:49:30 +01:00
__gu_err = __get_user_fn ( & __x , ptr , \
sizeof ( * ( ptr ) ) ) ; \
2006-02-03 20:11:52 -05:00
( x ) = * ( __force __typeof__ ( * ( ptr ) ) * ) & __x ; \
2005-11-07 00:59:11 -08:00
break ; \
} ; \
case 4 : { \
2016-08-21 22:00:54 -04:00
unsigned int __x = 0 ; \
2014-01-22 14:49:30 +01:00
__gu_err = __get_user_fn ( & __x , ptr , \
sizeof ( * ( ptr ) ) ) ; \
2006-02-03 20:11:52 -05:00
( x ) = * ( __force __typeof__ ( * ( ptr ) ) * ) & __x ; \
2005-11-07 00:59:11 -08:00
break ; \
} ; \
case 8 : { \
2016-08-21 22:00:54 -04:00
unsigned long long __x = 0 ; \
2014-01-22 14:49:30 +01:00
__gu_err = __get_user_fn ( & __x , ptr , \
sizeof ( * ( ptr ) ) ) ; \
2006-02-03 20:11:52 -05:00
( x ) = * ( __force __typeof__ ( * ( ptr ) ) * ) & __x ; \
2005-04-16 15:20:36 -07:00
break ; \
2005-11-07 00:59:11 -08:00
} ; \
2005-04-16 15:20:36 -07:00
default : \
__get_user_bad ( ) ; \
break ; \
} \
2016-06-13 10:17:20 +02:00
__builtin_expect ( __gu_err , 0 ) ; \
2005-04-16 15:20:36 -07:00
} )
# define get_user(x, ptr) \
( { \
2009-06-12 10:26:32 +02:00
might_fault ( ) ; \
2005-04-16 15:20:36 -07:00
__get_user ( x , ptr ) ; \
} )
2014-01-23 11:18:36 +01:00
int __get_user_bad ( void ) __attribute__ ( ( noreturn ) ) ;
2005-04-16 15:20:36 -07:00
2014-01-23 11:18:36 +01:00
unsigned long __must_check
2017-03-28 15:06:24 -04:00
raw_copy_in_user ( void __user * to , const void __user * from , unsigned long n ) ;
2005-04-16 15:20:36 -07:00
/*
* Copy a null terminated string from userspace .
*/
2014-01-23 11:18:36 +01:00
long __strncpy_from_user ( char * dst , const char __user * src , long count ) ;
2006-12-04 15:39:55 +01:00
static inline long __must_check
2005-04-16 15:20:36 -07:00
strncpy_from_user ( char * dst , const char __user * src , long count )
{
2009-06-12 10:26:32 +02:00
might_fault ( ) ;
2014-01-23 11:18:36 +01:00
return __strncpy_from_user ( dst , src , count ) ;
2005-04-16 15:20:36 -07:00
}
2014-01-24 12:51:27 +01:00
unsigned long __must_check __strnlen_user ( const char __user * src , unsigned long count ) ;
2014-01-23 11:18:36 +01:00
2014-01-24 12:51:27 +01:00
static inline unsigned long strnlen_user ( const char __user * src , unsigned long n )
2005-04-16 15:20:36 -07:00
{
2009-06-12 10:26:32 +02:00
might_fault ( ) ;
2014-01-23 11:18:36 +01:00
return __strnlen_user ( src , n ) ;
2005-04-16 15:20:36 -07:00
}
/*
* Zero Userspace
*/
2014-01-24 12:51:27 +01:00
unsigned long __must_check __clear_user ( void __user * to , unsigned long size ) ;
2005-04-16 15:20:36 -07:00
2014-01-24 12:51:27 +01:00
static inline unsigned long __must_check clear_user ( void __user * to , unsigned long n )
2005-04-16 15:20:36 -07:00
{
2009-06-12 10:26:32 +02:00
might_fault ( ) ;
2014-01-23 11:18:36 +01:00
return __clear_user ( to , n ) ;
2005-04-16 15:20:36 -07:00
}
2014-01-24 12:51:27 +01:00
int copy_to_user_real ( void __user * dest , void * src , unsigned long count ) ;
2015-03-13 12:55:56 +01:00
void s390_kernel_write ( void * dst , const void * src , size_t size ) ;
2012-03-28 18:30:02 +01:00
2005-04-16 15:20:36 -07:00
# endif /* __S390_UACCESS_H */