123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- /* SPDX-License-Identifier: GPL-2.0-only */
- #include <linux/linkage.h>
- #include <asm/asm.h>
- #include <asm/export.h>
- /*
- * Most CPUs support enhanced REP MOVSB/STOSB instructions. It is
- * recommended to use this when possible and we do use them by default.
- * If enhanced REP MOVSB/STOSB is not available, try to use fast string.
- * Otherwise, use original.
- */
- /*
- * Zero a page.
- * %rdi - page
- */
- SYM_FUNC_START(clear_page_rep)
- movl $4096/8,%ecx
- xorl %eax,%eax
- rep stosq
- RET
- SYM_FUNC_END(clear_page_rep)
- EXPORT_SYMBOL_GPL(clear_page_rep)
- SYM_FUNC_START(clear_page_orig)
- xorl %eax,%eax
- movl $4096/64,%ecx
- .p2align 4
- .Lloop:
- decl %ecx
- #define PUT(x) movq %rax,x*8(%rdi)
- movq %rax,(%rdi)
- PUT(1)
- PUT(2)
- PUT(3)
- PUT(4)
- PUT(5)
- PUT(6)
- PUT(7)
- leaq 64(%rdi),%rdi
- jnz .Lloop
- nop
- RET
- SYM_FUNC_END(clear_page_orig)
- EXPORT_SYMBOL_GPL(clear_page_orig)
- SYM_FUNC_START(clear_page_erms)
- movl $4096,%ecx
- xorl %eax,%eax
- rep stosb
- RET
- SYM_FUNC_END(clear_page_erms)
- EXPORT_SYMBOL_GPL(clear_page_erms)
- /*
- * Default clear user-space.
- * Input:
- * rdi destination
- * rcx count
- *
- * Output:
- * rcx: uncleared bytes or 0 if successful.
- */
- SYM_FUNC_START(clear_user_original)
- /*
- * Copy only the lower 32 bits of size as that is enough to handle the rest bytes,
- * i.e., no need for a 'q' suffix and thus a REX prefix.
- */
- mov %ecx,%eax
- shr $3,%rcx
- jz .Lrest_bytes
- # do the qwords first
- .p2align 4
- .Lqwords:
- movq $0,(%rdi)
- lea 8(%rdi),%rdi
- dec %rcx
- jnz .Lqwords
- .Lrest_bytes:
- and $7, %eax
- jz .Lexit
- # now do the rest bytes
- .Lbytes:
- movb $0,(%rdi)
- inc %rdi
- dec %eax
- jnz .Lbytes
- .Lexit:
- /*
- * %rax still needs to be cleared in the exception case because this function is called
- * from inline asm and the compiler expects %rax to be zero when exiting the inline asm,
- * in case it might reuse it somewhere.
- */
- xor %eax,%eax
- RET
- .Lqwords_exception:
- # convert remaining qwords back into bytes to return to caller
- shl $3, %rcx
- and $7, %eax
- add %rax,%rcx
- jmp .Lexit
- .Lbytes_exception:
- mov %eax,%ecx
- jmp .Lexit
- _ASM_EXTABLE_UA(.Lqwords, .Lqwords_exception)
- _ASM_EXTABLE_UA(.Lbytes, .Lbytes_exception)
- SYM_FUNC_END(clear_user_original)
- EXPORT_SYMBOL(clear_user_original)
- /*
- * Alternative clear user-space when CPU feature X86_FEATURE_REP_GOOD is
- * present.
- * Input:
- * rdi destination
- * rcx count
- *
- * Output:
- * rcx: uncleared bytes or 0 if successful.
- */
- SYM_FUNC_START(clear_user_rep_good)
- # call the original thing for less than a cacheline
- cmp $64, %rcx
- jb clear_user_original
- .Lprep:
- # copy lower 32-bits for rest bytes
- mov %ecx, %edx
- shr $3, %rcx
- jz .Lrep_good_rest_bytes
- .Lrep_good_qwords:
- rep stosq
- .Lrep_good_rest_bytes:
- and $7, %edx
- jz .Lrep_good_exit
- mov %edx, %ecx
- .Lrep_good_bytes:
- rep stosb
- .Lrep_good_exit:
- # see .Lexit comment above
- xor %eax, %eax
- RET
- .Lrep_good_qwords_exception:
- # convert remaining qwords back into bytes to return to caller
- shl $3, %rcx
- and $7, %edx
- add %rdx, %rcx
- jmp .Lrep_good_exit
- _ASM_EXTABLE_UA(.Lrep_good_qwords, .Lrep_good_qwords_exception)
- _ASM_EXTABLE_UA(.Lrep_good_bytes, .Lrep_good_exit)
- SYM_FUNC_END(clear_user_rep_good)
- EXPORT_SYMBOL(clear_user_rep_good)
- /*
- * Alternative clear user-space when CPU feature X86_FEATURE_ERMS is present.
- * Input:
- * rdi destination
- * rcx count
- *
- * Output:
- * rcx: uncleared bytes or 0 if successful.
- *
- */
- SYM_FUNC_START(clear_user_erms)
- # call the original thing for less than a cacheline
- cmp $64, %rcx
- jb clear_user_original
- .Lerms_bytes:
- rep stosb
- .Lerms_exit:
- xorl %eax,%eax
- RET
- _ASM_EXTABLE_UA(.Lerms_bytes, .Lerms_exit)
- SYM_FUNC_END(clear_user_erms)
- EXPORT_SYMBOL(clear_user_erms)
|