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/page_types.h>
  30#include <asm/errno.h>
  31#include <asm/asm-offsets.h>
  32#include <asm/thread_info.h>
  33#include <asm/asm.h>
  34#include <asm/smap.h>
  35#include <asm/export.h>
  36
  37        .text
  38ENTRY(__get_user_1)
  39        mov PER_CPU_VAR(current_task), %_ASM_DX
  40        cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
  41        jae bad_get_user
  42        ASM_STAC
  431:      movzbl (%_ASM_AX),%edx
  44        xor %eax,%eax
  45        ASM_CLAC
  46        ret
  47ENDPROC(__get_user_1)
  48EXPORT_SYMBOL(__get_user_1)
  49
  50ENTRY(__get_user_2)
  51        add $1,%_ASM_AX
  52        jc bad_get_user
  53        mov PER_CPU_VAR(current_task), %_ASM_DX
  54        cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
  55        jae bad_get_user
  56        ASM_STAC
  572:      movzwl -1(%_ASM_AX),%edx
  58        xor %eax,%eax
  59        ASM_CLAC
  60        ret
  61ENDPROC(__get_user_2)
  62EXPORT_SYMBOL(__get_user_2)
  63
  64ENTRY(__get_user_4)
  65        add $3,%_ASM_AX
  66        jc bad_get_user
  67        mov PER_CPU_VAR(current_task), %_ASM_DX
  68        cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
  69        jae bad_get_user
  70        ASM_STAC
  713:      movl -3(%_ASM_AX),%edx
  72        xor %eax,%eax
  73        ASM_CLAC
  74        ret
  75ENDPROC(__get_user_4)
  76EXPORT_SYMBOL(__get_user_4)
  77
  78ENTRY(__get_user_8)
  79#ifdef CONFIG_X86_64
  80        add $7,%_ASM_AX
  81        jc bad_get_user
  82        mov PER_CPU_VAR(current_task), %_ASM_DX
  83        cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
  84        jae bad_get_user
  85        ASM_STAC
  864:      movq -7(%_ASM_AX),%rdx
  87        xor %eax,%eax
  88        ASM_CLAC
  89        ret
  90#else
  91        add $7,%_ASM_AX
  92        jc bad_get_user_8
  93        mov PER_CPU_VAR(current_task), %_ASM_DX
  94        cmp TASK_addr_limit(%_ASM_DX),%_ASM_AX
  95        jae bad_get_user_8
  96        ASM_STAC
  974:      movl -7(%_ASM_AX),%edx
  985:      movl -3(%_ASM_AX),%ecx
  99        xor %eax,%eax
 100        ASM_CLAC
 101        ret
 102#endif
 103ENDPROC(__get_user_8)
 104EXPORT_SYMBOL(__get_user_8)
 105
 106
 107bad_get_user:
 108        xor %edx,%edx
 109        mov $(-EFAULT),%_ASM_AX
 110        ASM_CLAC
 111        ret
 112END(bad_get_user)
 113
 114#ifdef CONFIG_X86_32
 115bad_get_user_8:
 116        xor %edx,%edx
 117        xor %ecx,%ecx
 118        mov $(-EFAULT),%_ASM_AX
 119        ASM_CLAC
 120        ret
 121END(bad_get_user_8)
 122#endif
 123
 124        _ASM_EXTABLE(1b,bad_get_user)
 125        _ASM_EXTABLE(2b,bad_get_user)
 126        _ASM_EXTABLE(3b,bad_get_user)
 127#ifdef CONFIG_X86_64
 128        _ASM_EXTABLE(4b,bad_get_user)
 129#else
 130        _ASM_EXTABLE(4b,bad_get_user_8)
 131        _ASM_EXTABLE(5b,bad_get_user_8)
 132#endif
 133