11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * __put_user functions. 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (C) Copyright 2005 Linus Torvalds 55cbbc3b1eb37bdc72eefd2de03b39f5e784400c2Glauber Costa * (C) Copyright 2005 Andi Kleen 65cbbc3b1eb37bdc72eefd2de03b39f5e784400c2Glauber Costa * (C) Copyright 2008 Glauber Costa 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * These functions have a non-standard call interface 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to make them more efficient, especially as they 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return an error value in addition to the "real" 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * return value. 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1300e065ea587363e538d9624eea8cacad12cb7397Jan Beulich#include <linux/linkage.h> 1400e065ea587363e538d9624eea8cacad12cb7397Jan Beulich#include <asm/dwarf2.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/thread_info.h> 165cbbc3b1eb37bdc72eefd2de03b39f5e784400c2Glauber Costa#include <asm/errno.h> 172528de431ddb200653d1dc6ca90074bad9520f09Glauber Costa#include <asm/asm.h> 1863bcff2a307b9bcc712a8251eb27df8b2e117967H. Peter Anvin#include <asm/smap.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * __put_user_X 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Inputs: %eax[:%edx] contains the data 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * %ecx contains the address 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Outputs: %eax is error code (0 or -EFAULT) 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * These functions should not modify any other registers, 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * as they get called from within inline assembly. 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3300e065ea587363e538d9624eea8cacad12cb7397Jan Beulich#define ENTER CFI_STARTPROC ; \ 342528de431ddb200653d1dc6ca90074bad9520f09Glauber Costa GET_THREAD_INFO(%_ASM_BX) 3563bcff2a307b9bcc712a8251eb27df8b2e117967H. Peter Anvin#define EXIT ASM_CLAC ; \ 3663bcff2a307b9bcc712a8251eb27df8b2e117967H. Peter Anvin ret ; \ 3700e065ea587363e538d9624eea8cacad12cb7397Jan Beulich CFI_ENDPROC 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds.text 4000e065ea587363e538d9624eea8cacad12cb7397Jan BeulichENTRY(__put_user_1) 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ENTER 422528de431ddb200653d1dc6ca90074bad9520f09Glauber Costa cmp TI_addr_limit(%_ASM_BX),%_ASM_CX 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds jae bad_put_user 4463bcff2a307b9bcc712a8251eb27df8b2e117967H. Peter Anvin ASM_STAC 452528de431ddb200653d1dc6ca90074bad9520f09Glauber Costa1: movb %al,(%_ASM_CX) 46efea505d83873cfc8a7cdbb8a2a11d2c67467843Glauber Costa xor %eax,%eax 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EXIT 4800e065ea587363e538d9624eea8cacad12cb7397Jan BeulichENDPROC(__put_user_1) 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5000e065ea587363e538d9624eea8cacad12cb7397Jan BeulichENTRY(__put_user_2) 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ENTER 522528de431ddb200653d1dc6ca90074bad9520f09Glauber Costa mov TI_addr_limit(%_ASM_BX),%_ASM_BX 532528de431ddb200653d1dc6ca90074bad9520f09Glauber Costa sub $1,%_ASM_BX 542528de431ddb200653d1dc6ca90074bad9520f09Glauber Costa cmp %_ASM_BX,%_ASM_CX 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds jae bad_put_user 5663bcff2a307b9bcc712a8251eb27df8b2e117967H. Peter Anvin ASM_STAC 572528de431ddb200653d1dc6ca90074bad9520f09Glauber Costa2: movw %ax,(%_ASM_CX) 58efea505d83873cfc8a7cdbb8a2a11d2c67467843Glauber Costa xor %eax,%eax 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EXIT 6000e065ea587363e538d9624eea8cacad12cb7397Jan BeulichENDPROC(__put_user_2) 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6200e065ea587363e538d9624eea8cacad12cb7397Jan BeulichENTRY(__put_user_4) 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ENTER 642528de431ddb200653d1dc6ca90074bad9520f09Glauber Costa mov TI_addr_limit(%_ASM_BX),%_ASM_BX 652528de431ddb200653d1dc6ca90074bad9520f09Glauber Costa sub $3,%_ASM_BX 662528de431ddb200653d1dc6ca90074bad9520f09Glauber Costa cmp %_ASM_BX,%_ASM_CX 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds jae bad_put_user 6863bcff2a307b9bcc712a8251eb27df8b2e117967H. Peter Anvin ASM_STAC 692528de431ddb200653d1dc6ca90074bad9520f09Glauber Costa3: movl %eax,(%_ASM_CX) 70efea505d83873cfc8a7cdbb8a2a11d2c67467843Glauber Costa xor %eax,%eax 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EXIT 7200e065ea587363e538d9624eea8cacad12cb7397Jan BeulichENDPROC(__put_user_4) 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7400e065ea587363e538d9624eea8cacad12cb7397Jan BeulichENTRY(__put_user_8) 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ENTER 762528de431ddb200653d1dc6ca90074bad9520f09Glauber Costa mov TI_addr_limit(%_ASM_BX),%_ASM_BX 772528de431ddb200653d1dc6ca90074bad9520f09Glauber Costa sub $7,%_ASM_BX 782528de431ddb200653d1dc6ca90074bad9520f09Glauber Costa cmp %_ASM_BX,%_ASM_CX 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds jae bad_put_user 8063bcff2a307b9bcc712a8251eb27df8b2e117967H. Peter Anvin ASM_STAC 815cbbc3b1eb37bdc72eefd2de03b39f5e784400c2Glauber Costa4: mov %_ASM_AX,(%_ASM_CX) 825cbbc3b1eb37bdc72eefd2de03b39f5e784400c2Glauber Costa#ifdef CONFIG_X86_32 832528de431ddb200653d1dc6ca90074bad9520f09Glauber Costa5: movl %edx,4(%_ASM_CX) 845cbbc3b1eb37bdc72eefd2de03b39f5e784400c2Glauber Costa#endif 85efea505d83873cfc8a7cdbb8a2a11d2c67467843Glauber Costa xor %eax,%eax 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EXIT 8700e065ea587363e538d9624eea8cacad12cb7397Jan BeulichENDPROC(__put_user_8) 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsbad_put_user: 90268cf048c890d10bd3a86bd87922ed8a722d502fGlauber Costa CFI_STARTPROC 915cbbc3b1eb37bdc72eefd2de03b39f5e784400c2Glauber Costa movl $-EFAULT,%eax 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds EXIT 9300e065ea587363e538d9624eea8cacad12cb7397Jan BeulichEND(bad_put_user) 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 95a53a96e5413d3639ed75d202bbfe68aa0a56c091H. Peter Anvin _ASM_EXTABLE(1b,bad_put_user) 96a53a96e5413d3639ed75d202bbfe68aa0a56c091H. Peter Anvin _ASM_EXTABLE(2b,bad_put_user) 97a53a96e5413d3639ed75d202bbfe68aa0a56c091H. Peter Anvin _ASM_EXTABLE(3b,bad_put_user) 98a53a96e5413d3639ed75d202bbfe68aa0a56c091H. Peter Anvin _ASM_EXTABLE(4b,bad_put_user) 995cbbc3b1eb37bdc72eefd2de03b39f5e784400c2Glauber Costa#ifdef CONFIG_X86_32 100a53a96e5413d3639ed75d202bbfe68aa0a56c091H. Peter Anvin _ASM_EXTABLE(5b,bad_put_user) 1015cbbc3b1eb37bdc72eefd2de03b39f5e784400c2Glauber Costa#endif 102