x86: bring back rep movsq for user access on CPUs without ERMS
[linux-2.6-block.git] / arch / x86 / lib / copy_user_64.S
CommitLineData
3fc21751 1/* SPDX-License-Identifier: GPL-2.0-only */
ad2fc2cd
VM
2/*
3 * Copyright 2008 Vitaly Mayatskikh <vmayatsk@redhat.com>
4 * Copyright 2002 Andi Kleen, SuSE Labs.
ad2fc2cd
VM
5 *
6 * Functions to copy from and to user space.
7 */
1da177e4 8
8d379dad 9#include <linux/linkage.h>
47ee3f1d
LT
10#include <asm/cpufeatures.h>
11#include <asm/alternative.h>
9732da8c 12#include <asm/asm.h>
784d5699 13#include <asm/export.h>
3022d734 14
1da177e4 15/*
427fda2c
LT
16 * rep_movs_alternative - memory copy with exception handling.
17 * This version is for CPUs that don't have FSRM (Fast Short Rep Movs)
ad2fc2cd
VM
18 *
19 * Input:
1da177e4
LT
20 * rdi destination
21 * rsi source
577e6a7f 22 * rcx count
1da177e4 23 *
ad2fc2cd 24 * Output:
577e6a7f
LT
25 * rcx uncopied bytes or 0 if successful.
26 *
27 * NOTE! The calling convention is very intentionally the same as
28 * for 'rep movs', so that we can rewrite the function call with
427fda2c 29 * just a plain 'rep movs' on machines that have FSRM. But to make
ca96b162 30 * it simpler for us, we can clobber rsi/rdi and rax freely.
1da177e4 31 */
427fda2c
LT
32SYM_FUNC_START(rep_movs_alternative)
33 cmpq $64,%rcx
47ee3f1d 34 jae .Llarge
7bcd3f34 35
427fda2c
LT
36 cmp $8,%ecx
37 jae .Lword
7bcd3f34 38
427fda2c
LT
39 testl %ecx,%ecx
40 je .Lexit
8d379dad 41
427fda2c
LT
42.Lcopy_user_tail:
430: movb (%rsi),%al
441: movb %al,(%rdi)
45 inc %rdi
46 inc %rsi
47 dec %rcx
48 jne .Lcopy_user_tail
49.Lexit:
f94909ce 50 RET
3693ca81 51
427fda2c
LT
52 _ASM_EXTABLE_UA( 0b, .Lexit)
53 _ASM_EXTABLE_UA( 1b, .Lexit)
33761363 54
427fda2c
LT
55 .p2align 4
56.Lword:
572: movq (%rsi),%rax
583: movq %rax,(%rdi)
59 addq $8,%rsi
60 addq $8,%rdi
61 sub $8,%ecx
62 je .Lexit
63 cmp $8,%ecx
64 jae .Lword
65 jmp .Lcopy_user_tail
acba44d2 66
427fda2c
LT
67 _ASM_EXTABLE_UA( 2b, .Lcopy_user_tail)
68 _ASM_EXTABLE_UA( 3b, .Lcopy_user_tail)
acba44d2 69
47ee3f1d 70.Llarge:
ca96b162 710: ALTERNATIVE "jmp .Llarge_movsq", "rep movsb", X86_FEATURE_ERMS
47ee3f1d
LT
721: RET
73
ca96b162 74 _ASM_EXTABLE_UA( 0b, 1b)
47ee3f1d 75
ca96b162
MG
76.Llarge_movsq:
77 movq %rcx,%rax
78 shrq $3,%rcx
79 andl $7,%eax
800: rep movsq
81 movl %eax,%ecx
427fda2c
LT
82 testl %ecx,%ecx
83 jne .Lcopy_user_tail
84 RET
85
ca96b162
MG
861: leaq (%rax,%rcx,8),%rcx
87 jmp .Lcopy_user_tail
88
89 _ASM_EXTABLE_UA( 0b, 1b)
427fda2c
LT
90SYM_FUNC_END(rep_movs_alternative)
91EXPORT_SYMBOL(rep_movs_alternative)