Commit | Line | Data |
---|---|---|
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 |
32 | SYM_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: |
43 | 0: movb (%rsi),%al | |
44 | 1: 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: | |
57 | 2: movq (%rsi),%rax | |
58 | 3: 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 | 71 | 0: ALTERNATIVE "jmp .Llarge_movsq", "rep movsb", X86_FEATURE_ERMS |
47ee3f1d LT |
72 | 1: 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 | |
80 | 0: rep movsq | |
81 | movl %eax,%ecx | |
427fda2c LT |
82 | testl %ecx,%ecx |
83 | jne .Lcopy_user_tail | |
84 | RET | |
85 | ||
ca96b162 MG |
86 | 1: leaq (%rax,%rcx,8),%rcx |
87 | jmp .Lcopy_user_tail | |
88 | ||
89 | _ASM_EXTABLE_UA( 0b, 1b) | |
427fda2c LT |
90 | SYM_FUNC_END(rep_movs_alternative) |
91 | EXPORT_SYMBOL(rep_movs_alternative) |