linux/arch/x86/lib/getuser.S
<<
>>
Prefs
   1/*
   2 * __get_user functions.
   3 *
   4 * (C) Copyright 1998 Linus Torvalds
   5 * (C) Copyright 2005 Andi Kleen
   6 * (C) Copyright 2008 Glauber Costa
   7 *
   8 * These functions have a non-standard call interface
   9 * to make them more efficient, especially as they
  10 * return an error value in addition to the "real"
  11 * return value.
  12 */
  13
  14/*
  15 * __get_user_X
  16 *
  17 * Inputs:      %[r|e]ax contains the address.
  18 *
  19 * Outputs:     %[r|e]ax is error code (0 or -EFAULT)
  20 *              %[r|e]dx contains zero-extended value
  21 *              %ecx contains the high half for 32-bit __get_user_8
  22 *
  23 *
  24 * These functions should not modify any other registers,
  25 * as they get called from within inline assembly.
  26 */
  27
  28#include <linux/linkage.h>
  29#include <asm/dwarf2.h>
  30#include <asm/page_types.h>
  31#include <asm/errno.h>
  32#include <asm/asm-offsets.h>
  33#include <asm/thread_info.h>
  34#include <asm/asm.h>
  35#include <asm/smap.h>
  36
  37        .text
  38ENTRY(__get_user_1)
  39        CFI_STARTPROC
  40        GET_THREAD_INFO(%_ASM_DX)
  41        cmp TI_addr_limit(%_ASM_DX),%_ASM_AX
  42        jae bad_get_user
  43        ASM_STAC
  441:      movzbl (%_ASM_AX),%edx
  45        xor %eax,%eax
  46        ASM_CLAC
  47        ret
  48        CFI_ENDPROC
  49ENDPROC(__get_user_1)
  50
  51ENTRY(__get_user_2)
  52        CFI_STARTPROC
  53        add $1,%_ASM_AX
  54        jc bad_get_user
  55        GET_THREAD_INFO(%_ASM_DX)
  56        cmp TI_addr_limit(%_ASM_DX),%_ASM_AX
  57        jae bad_get_user
  58        ASM_STAC
  592:      movzwl -1(%_ASM_AX),%edx
  60        xor %eax,%eax
  61        ASM_CLAC
  62        ret
  63        CFI_ENDPROC
  64ENDPROC(__get_user_2)
  65
  66ENTRY(__get_user_4)
  67        CFI_STARTPROC
  68        add $3,%_ASM_AX
  69        jc bad_get_user
  70        GET_THREAD_INFO(%_ASM_DX)
  71        cmp TI_addr_limit(%_ASM_DX),%_ASM_AX
  72        jae bad_get_user
  73        ASM_STAC
  743:      movl -3(%_ASM_AX),%edx
  75        xor %eax,%eax
  76        ASM_CLAC
  77        ret
  78        CFI_ENDPROC
  79ENDPROC(__get_user_4)
  80
  81ENTRY(__get_user_8)
  82        CFI_STARTPROC
  83#ifdef CONFIG_X86_64
  84        add $7,%_ASM_AX
  85        jc bad_get_user
  86        GET_THREAD_INFO(%_ASM_DX)
  87        cmp TI_addr_limit(%_ASM_DX),%_ASM_AX
  88        jae bad_get_user
  89        ASM_STAC
  904:      movq -7(%_ASM_AX),%rdx
  91        xor %eax,%eax
  92        ASM_CLAC
  93        ret
  94#else
  95        add $7,%_ASM_AX
  96        jc bad_get_user_8
  97        GET_THREAD_INFO(%_ASM_DX)
  98        cmp TI_addr_limit(%_ASM_DX),%_ASM_AX
  99        jae bad_get_user_8
 100        ASM_STAC
 1014:      movl -7(%_ASM_AX),%edx
 1025:      movl -3(%_ASM_AX),%ecx
 103        xor %eax,%eax
 104        ASM_CLAC
 105        ret
 106#endif
 107        CFI_ENDPROC
 108ENDPROC(__get_user_8)
 109
 110
 111bad_get_user:
 112        CFI_STARTPROC
 113        xor %edx,%edx
 114        mov $(-EFAULT),%_ASM_AX
 115        ASM_CLAC
 116        ret
 117        CFI_ENDPROC
 118END(bad_get_user)
 119
 120#ifdef CONFIG_X86_32
 121bad_get_user_8:
 122        CFI_STARTPROC
 123        xor %edx,%edx
 124        xor %ecx,%ecx
 125        mov $(-EFAULT),%_ASM_AX
 126        ASM_CLAC
 127        ret
 128        CFI_ENDPROC
 129END(bad_get_user_8)
 130#endif
 131
 132        _ASM_EXTABLE(1b,bad_get_user)
 133        _ASM_EXTABLE(2b,bad_get_user)
 134        _ASM_EXTABLE(3b,bad_get_user)
 135#ifdef CONFIG_X86_64
 136        _ASM_EXTABLE(4b,bad_get_user)
 137#else
 138        _ASM_EXTABLE(4b,bad_get_user_8)
 139        _ASM_EXTABLE(5b,bad_get_user_8)
 140#endif
 141