1/* 2 * __put_user functions. 3 * 4 * (C) Copyright 2005 Linus Torvalds 5 * 6 * These functions have a non-standard call interface 7 * to make them more efficient, especially as they 8 * return an error value in addition to the "real" 9 * return value. 10 */ 11#include <linux/linkage.h> 12#include <asm/dwarf2.h> 13#include <asm/thread_info.h> 14 15 16/* 17 * __put_user_X 18 * 19 * Inputs: %eax[:%edx] contains the data 20 * %ecx contains the address 21 * 22 * Outputs: %eax is error code (0 or -EFAULT) 23 * 24 * These functions should not modify any other registers, 25 * as they get called from within inline assembly. 26 */ 27 28#define ENTER CFI_STARTPROC ; \ 29 pushl %ebx ; \ 30 CFI_ADJUST_CFA_OFFSET 4 ; \ 31 CFI_REL_OFFSET ebx, 0 ; \ 32 GET_THREAD_INFO(%ebx) 33#define EXIT popl %ebx ; \ 34 CFI_ADJUST_CFA_OFFSET -4 ; \ 35 CFI_RESTORE ebx ; \ 36 ret ; \ 37 CFI_ENDPROC 38 39.text 40ENTRY(__put_user_1) 41 ENTER 42 cmpl TI_addr_limit(%ebx),%ecx 43 jae bad_put_user 441: movb %al,(%ecx) 45 xorl %eax,%eax 46 EXIT 47ENDPROC(__put_user_1) 48 49ENTRY(__put_user_2) 50 ENTER 51 movl TI_addr_limit(%ebx),%ebx 52 subl $1,%ebx 53 cmpl %ebx,%ecx 54 jae bad_put_user 552: movw %ax,(%ecx) 56 xorl %eax,%eax 57 EXIT 58ENDPROC(__put_user_2) 59 60ENTRY(__put_user_4) 61 ENTER 62 movl TI_addr_limit(%ebx),%ebx 63 subl $3,%ebx 64 cmpl %ebx,%ecx 65 jae bad_put_user 663: movl %eax,(%ecx) 67 xorl %eax,%eax 68 EXIT 69ENDPROC(__put_user_4) 70 71ENTRY(__put_user_8) 72 ENTER 73 movl TI_addr_limit(%ebx),%ebx 74 subl $7,%ebx 75 cmpl %ebx,%ecx 76 jae bad_put_user 774: movl %eax,(%ecx) 785: movl %edx,4(%ecx) 79 xorl %eax,%eax 80 EXIT 81ENDPROC(__put_user_8) 82 83bad_put_user: 84 CFI_STARTPROC simple 85 CFI_DEF_CFA esp, 2*4 86 CFI_OFFSET eip, -1*4 87 CFI_OFFSET ebx, -2*4 88 movl $-14,%eax 89 EXIT 90END(bad_put_user) 91 92.section __ex_table,"a" 93 .long 1b,bad_put_user 94 .long 2b,bad_put_user 95 .long 3b,bad_put_user 96 .long 4b,bad_put_user 97 .long 5b,bad_put_user 98.previous 99