1/* SPDX-License-Identifier: GPL-2.0-only */ 2#include <linux/export.h> 3#include <linux/linkage.h> 4#include <linux/cfi_types.h> 5#include <linux/objtool.h> 6#include <asm/asm.h> 7 8/* 9 * Zero page aligned region. 10 * %rdi - dest 11 * %rcx - length 12 */ 13SYM_TYPED_FUNC_START(__clear_pages_unrolled) 14 shrq $6, %rcx 15 .p2align 4 16.Lloop: 17 decq %rcx 18#define PUT(x) movq %rax,x*8(%rdi) 19 movq %rax,(%rdi) 20 PUT(1) 21 PUT(2) 22 PUT(3) 23 PUT(4) 24 PUT(5) 25 PUT(6) 26 PUT(7) 27 leaq 64(%rdi),%rdi 28 jnz .Lloop 29 nop 30 RET 31SYM_FUNC_END(__clear_pages_unrolled) 32EXPORT_SYMBOL_GPL(__clear_pages_unrolled) 33 34/* 35 * Default clear user-space. 36 * Input: 37 * rdi destination 38 * rcx count 39 * rax is zero 40 * 41 * Output: 42 * rcx: uncleared bytes or 0 if successful. 43 */ 44SYM_FUNC_START(rep_stos_alternative) 45 ANNOTATE_NOENDBR 46 cmpq $64,%rcx 47 jae .Lunrolled 48 49 cmp $8,%ecx 50 jae .Lword 51 52 testl %ecx,%ecx 53 je .Lexit 54 55.Lclear_user_tail: 560: movb %al,(%rdi) 57 inc %rdi 58 dec %rcx 59 jnz .Lclear_user_tail 60.Lexit: 61 RET 62 63 _ASM_EXTABLE_UA( 0b, .Lexit) 64 65.Lword: 661: movq %rax,(%rdi) 67 addq $8,%rdi 68 sub $8,%ecx 69 je .Lexit 70 cmp $8,%ecx 71 jae .Lword 72 jmp .Lclear_user_tail 73 74 .p2align 4 75.Lunrolled: 7610: movq %rax,(%rdi) 7711: movq %rax,8(%rdi) 7812: movq %rax,16(%rdi) 7913: movq %rax,24(%rdi) 8014: movq %rax,32(%rdi) 8115: movq %rax,40(%rdi) 8216: movq %rax,48(%rdi) 8317: movq %rax,56(%rdi) 84 addq $64,%rdi 85 subq $64,%rcx 86 cmpq $64,%rcx 87 jae .Lunrolled 88 cmpl $8,%ecx 89 jae .Lword 90 testl %ecx,%ecx 91 jne .Lclear_user_tail 92 RET 93 94 /* 95 * If we take an exception on any of the 96 * word stores, we know that %rcx isn't zero, 97 * so we can just go to the tail clearing to 98 * get the exact count. 99 * 100 * The unrolled case might end up clearing 101 * some bytes twice. Don't care. 102 * 103 * We could use the value in %rdi to avoid 104 * a second fault on the exact count case, 105 * but do we really care? No. 106 * 107 * Finally, we could try to align %rdi at the 108 * top of the unrolling. But unaligned stores 109 * just aren't that common or expensive. 110 */ 111 _ASM_EXTABLE_UA( 1b, .Lclear_user_tail) 112 _ASM_EXTABLE_UA(10b, .Lclear_user_tail) 113 _ASM_EXTABLE_UA(11b, .Lclear_user_tail) 114 _ASM_EXTABLE_UA(12b, .Lclear_user_tail) 115 _ASM_EXTABLE_UA(13b, .Lclear_user_tail) 116 _ASM_EXTABLE_UA(14b, .Lclear_user_tail) 117 _ASM_EXTABLE_UA(15b, .Lclear_user_tail) 118 _ASM_EXTABLE_UA(16b, .Lclear_user_tail) 119 _ASM_EXTABLE_UA(17b, .Lclear_user_tail) 120SYM_FUNC_END(rep_stos_alternative) 121EXPORT_SYMBOL(rep_stos_alternative) 122