162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2020-2022 Loongson Technology Corporation Limited 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/export.h> 762306a36Sopenharmony_ci#include <asm/alternative-asm.h> 862306a36Sopenharmony_ci#include <asm/asm.h> 962306a36Sopenharmony_ci#include <asm/asmmacro.h> 1062306a36Sopenharmony_ci#include <asm/asm-extable.h> 1162306a36Sopenharmony_ci#include <asm/cpu.h> 1262306a36Sopenharmony_ci#include <asm/regdef.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ciSYM_FUNC_START(__copy_user) 1562306a36Sopenharmony_ci /* 1662306a36Sopenharmony_ci * Some CPUs support hardware unaligned access 1762306a36Sopenharmony_ci */ 1862306a36Sopenharmony_ci ALTERNATIVE "b __copy_user_generic", \ 1962306a36Sopenharmony_ci "b __copy_user_fast", CPU_FEATURE_UAL 2062306a36Sopenharmony_ciSYM_FUNC_END(__copy_user) 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ciEXPORT_SYMBOL(__copy_user) 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci/* 2562306a36Sopenharmony_ci * unsigned long __copy_user_generic(void *to, const void *from, size_t n) 2662306a36Sopenharmony_ci * 2762306a36Sopenharmony_ci * a0: to 2862306a36Sopenharmony_ci * a1: from 2962306a36Sopenharmony_ci * a2: n 3062306a36Sopenharmony_ci */ 3162306a36Sopenharmony_ciSYM_FUNC_START(__copy_user_generic) 3262306a36Sopenharmony_ci beqz a2, 3f 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci1: ld.b t0, a1, 0 3562306a36Sopenharmony_ci2: st.b t0, a0, 0 3662306a36Sopenharmony_ci addi.d a0, a0, 1 3762306a36Sopenharmony_ci addi.d a1, a1, 1 3862306a36Sopenharmony_ci addi.d a2, a2, -1 3962306a36Sopenharmony_ci bgtz a2, 1b 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci3: move a0, a2 4262306a36Sopenharmony_ci jr ra 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci _asm_extable 1b, 3b 4562306a36Sopenharmony_ci _asm_extable 2b, 3b 4662306a36Sopenharmony_ciSYM_FUNC_END(__copy_user_generic) 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci/* 4962306a36Sopenharmony_ci * unsigned long __copy_user_fast(void *to, const void *from, unsigned long n) 5062306a36Sopenharmony_ci * 5162306a36Sopenharmony_ci * a0: to 5262306a36Sopenharmony_ci * a1: from 5362306a36Sopenharmony_ci * a2: n 5462306a36Sopenharmony_ci */ 5562306a36Sopenharmony_ciSYM_FUNC_START(__copy_user_fast) 5662306a36Sopenharmony_ci sltui t0, a2, 9 5762306a36Sopenharmony_ci bnez t0, .Lsmall 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci0: ld.d t0, a1, 0 6062306a36Sopenharmony_ci1: st.d t0, a0, 0 6162306a36Sopenharmony_ci add.d a3, a1, a2 6262306a36Sopenharmony_ci add.d a2, a0, a2 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci /* align up destination address */ 6562306a36Sopenharmony_ci andi t1, a0, 7 6662306a36Sopenharmony_ci sub.d t0, zero, t1 6762306a36Sopenharmony_ci addi.d t0, t0, 8 6862306a36Sopenharmony_ci add.d a1, a1, t0 6962306a36Sopenharmony_ci add.d a0, a0, t0 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci addi.d a4, a3, -64 7262306a36Sopenharmony_ci bgeu a1, a4, .Llt64 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci /* copy 64 bytes at a time */ 7562306a36Sopenharmony_ci.Lloop64: 7662306a36Sopenharmony_ci2: ld.d t0, a1, 0 7762306a36Sopenharmony_ci3: ld.d t1, a1, 8 7862306a36Sopenharmony_ci4: ld.d t2, a1, 16 7962306a36Sopenharmony_ci5: ld.d t3, a1, 24 8062306a36Sopenharmony_ci6: ld.d t4, a1, 32 8162306a36Sopenharmony_ci7: ld.d t5, a1, 40 8262306a36Sopenharmony_ci8: ld.d t6, a1, 48 8362306a36Sopenharmony_ci9: ld.d t7, a1, 56 8462306a36Sopenharmony_ci10: st.d t0, a0, 0 8562306a36Sopenharmony_ci11: st.d t1, a0, 8 8662306a36Sopenharmony_ci12: st.d t2, a0, 16 8762306a36Sopenharmony_ci13: st.d t3, a0, 24 8862306a36Sopenharmony_ci14: st.d t4, a0, 32 8962306a36Sopenharmony_ci15: st.d t5, a0, 40 9062306a36Sopenharmony_ci16: st.d t6, a0, 48 9162306a36Sopenharmony_ci17: st.d t7, a0, 56 9262306a36Sopenharmony_ci addi.d a1, a1, 64 9362306a36Sopenharmony_ci addi.d a0, a0, 64 9462306a36Sopenharmony_ci bltu a1, a4, .Lloop64 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci /* copy the remaining bytes */ 9762306a36Sopenharmony_ci.Llt64: 9862306a36Sopenharmony_ci addi.d a4, a3, -32 9962306a36Sopenharmony_ci bgeu a1, a4, .Llt32 10062306a36Sopenharmony_ci18: ld.d t0, a1, 0 10162306a36Sopenharmony_ci19: ld.d t1, a1, 8 10262306a36Sopenharmony_ci20: ld.d t2, a1, 16 10362306a36Sopenharmony_ci21: ld.d t3, a1, 24 10462306a36Sopenharmony_ci22: st.d t0, a0, 0 10562306a36Sopenharmony_ci23: st.d t1, a0, 8 10662306a36Sopenharmony_ci24: st.d t2, a0, 16 10762306a36Sopenharmony_ci25: st.d t3, a0, 24 10862306a36Sopenharmony_ci addi.d a1, a1, 32 10962306a36Sopenharmony_ci addi.d a0, a0, 32 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci.Llt32: 11262306a36Sopenharmony_ci addi.d a4, a3, -16 11362306a36Sopenharmony_ci bgeu a1, a4, .Llt16 11462306a36Sopenharmony_ci26: ld.d t0, a1, 0 11562306a36Sopenharmony_ci27: ld.d t1, a1, 8 11662306a36Sopenharmony_ci28: st.d t0, a0, 0 11762306a36Sopenharmony_ci29: st.d t1, a0, 8 11862306a36Sopenharmony_ci addi.d a1, a1, 16 11962306a36Sopenharmony_ci addi.d a0, a0, 16 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci.Llt16: 12262306a36Sopenharmony_ci addi.d a4, a3, -8 12362306a36Sopenharmony_ci bgeu a1, a4, .Llt8 12462306a36Sopenharmony_ci30: ld.d t0, a1, 0 12562306a36Sopenharmony_ci31: st.d t0, a0, 0 12662306a36Sopenharmony_ci addi.d a1, a1, 8 12762306a36Sopenharmony_ci addi.d a0, a0, 8 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci.Llt8: 13062306a36Sopenharmony_ci32: ld.d t0, a3, -8 13162306a36Sopenharmony_ci33: st.d t0, a2, -8 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci /* return */ 13462306a36Sopenharmony_ci move a0, zero 13562306a36Sopenharmony_ci jr ra 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci .align 5 13862306a36Sopenharmony_ci.Lsmall: 13962306a36Sopenharmony_ci pcaddi t0, 8 14062306a36Sopenharmony_ci slli.d a3, a2, 5 14162306a36Sopenharmony_ci add.d t0, t0, a3 14262306a36Sopenharmony_ci jr t0 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci .align 5 14562306a36Sopenharmony_ci move a0, zero 14662306a36Sopenharmony_ci jr ra 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci .align 5 14962306a36Sopenharmony_ci34: ld.b t0, a1, 0 15062306a36Sopenharmony_ci35: st.b t0, a0, 0 15162306a36Sopenharmony_ci move a0, zero 15262306a36Sopenharmony_ci jr ra 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci .align 5 15562306a36Sopenharmony_ci36: ld.h t0, a1, 0 15662306a36Sopenharmony_ci37: st.h t0, a0, 0 15762306a36Sopenharmony_ci move a0, zero 15862306a36Sopenharmony_ci jr ra 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci .align 5 16162306a36Sopenharmony_ci38: ld.h t0, a1, 0 16262306a36Sopenharmony_ci39: ld.b t1, a1, 2 16362306a36Sopenharmony_ci40: st.h t0, a0, 0 16462306a36Sopenharmony_ci41: st.b t1, a0, 2 16562306a36Sopenharmony_ci move a0, zero 16662306a36Sopenharmony_ci jr ra 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci .align 5 16962306a36Sopenharmony_ci42: ld.w t0, a1, 0 17062306a36Sopenharmony_ci43: st.w t0, a0, 0 17162306a36Sopenharmony_ci move a0, zero 17262306a36Sopenharmony_ci jr ra 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci .align 5 17562306a36Sopenharmony_ci44: ld.w t0, a1, 0 17662306a36Sopenharmony_ci45: ld.b t1, a1, 4 17762306a36Sopenharmony_ci46: st.w t0, a0, 0 17862306a36Sopenharmony_ci47: st.b t1, a0, 4 17962306a36Sopenharmony_ci move a0, zero 18062306a36Sopenharmony_ci jr ra 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci .align 5 18362306a36Sopenharmony_ci48: ld.w t0, a1, 0 18462306a36Sopenharmony_ci49: ld.h t1, a1, 4 18562306a36Sopenharmony_ci50: st.w t0, a0, 0 18662306a36Sopenharmony_ci51: st.h t1, a0, 4 18762306a36Sopenharmony_ci move a0, zero 18862306a36Sopenharmony_ci jr ra 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci .align 5 19162306a36Sopenharmony_ci52: ld.w t0, a1, 0 19262306a36Sopenharmony_ci53: ld.w t1, a1, 3 19362306a36Sopenharmony_ci54: st.w t0, a0, 0 19462306a36Sopenharmony_ci55: st.w t1, a0, 3 19562306a36Sopenharmony_ci move a0, zero 19662306a36Sopenharmony_ci jr ra 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci .align 5 19962306a36Sopenharmony_ci56: ld.d t0, a1, 0 20062306a36Sopenharmony_ci57: st.d t0, a0, 0 20162306a36Sopenharmony_ci move a0, zero 20262306a36Sopenharmony_ci jr ra 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci /* fixup and ex_table */ 20562306a36Sopenharmony_ci.Llarge_fixup: 20662306a36Sopenharmony_ci sub.d a2, a2, a0 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci.Lsmall_fixup: 20962306a36Sopenharmony_ci58: ld.b t0, a1, 0 21062306a36Sopenharmony_ci59: st.b t0, a0, 0 21162306a36Sopenharmony_ci addi.d a0, a0, 1 21262306a36Sopenharmony_ci addi.d a1, a1, 1 21362306a36Sopenharmony_ci addi.d a2, a2, -1 21462306a36Sopenharmony_ci bgt a2, zero, 58b 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci.Lexit: 21762306a36Sopenharmony_ci move a0, a2 21862306a36Sopenharmony_ci jr ra 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci _asm_extable 0b, .Lsmall_fixup 22162306a36Sopenharmony_ci _asm_extable 1b, .Lsmall_fixup 22262306a36Sopenharmony_ci _asm_extable 2b, .Llarge_fixup 22362306a36Sopenharmony_ci _asm_extable 3b, .Llarge_fixup 22462306a36Sopenharmony_ci _asm_extable 4b, .Llarge_fixup 22562306a36Sopenharmony_ci _asm_extable 5b, .Llarge_fixup 22662306a36Sopenharmony_ci _asm_extable 6b, .Llarge_fixup 22762306a36Sopenharmony_ci _asm_extable 7b, .Llarge_fixup 22862306a36Sopenharmony_ci _asm_extable 8b, .Llarge_fixup 22962306a36Sopenharmony_ci _asm_extable 9b, .Llarge_fixup 23062306a36Sopenharmony_ci _asm_extable 10b, .Llarge_fixup 23162306a36Sopenharmony_ci _asm_extable 11b, .Llarge_fixup 23262306a36Sopenharmony_ci _asm_extable 12b, .Llarge_fixup 23362306a36Sopenharmony_ci _asm_extable 13b, .Llarge_fixup 23462306a36Sopenharmony_ci _asm_extable 14b, .Llarge_fixup 23562306a36Sopenharmony_ci _asm_extable 15b, .Llarge_fixup 23662306a36Sopenharmony_ci _asm_extable 16b, .Llarge_fixup 23762306a36Sopenharmony_ci _asm_extable 17b, .Llarge_fixup 23862306a36Sopenharmony_ci _asm_extable 18b, .Llarge_fixup 23962306a36Sopenharmony_ci _asm_extable 19b, .Llarge_fixup 24062306a36Sopenharmony_ci _asm_extable 20b, .Llarge_fixup 24162306a36Sopenharmony_ci _asm_extable 21b, .Llarge_fixup 24262306a36Sopenharmony_ci _asm_extable 22b, .Llarge_fixup 24362306a36Sopenharmony_ci _asm_extable 23b, .Llarge_fixup 24462306a36Sopenharmony_ci _asm_extable 24b, .Llarge_fixup 24562306a36Sopenharmony_ci _asm_extable 25b, .Llarge_fixup 24662306a36Sopenharmony_ci _asm_extable 26b, .Llarge_fixup 24762306a36Sopenharmony_ci _asm_extable 27b, .Llarge_fixup 24862306a36Sopenharmony_ci _asm_extable 28b, .Llarge_fixup 24962306a36Sopenharmony_ci _asm_extable 29b, .Llarge_fixup 25062306a36Sopenharmony_ci _asm_extable 30b, .Llarge_fixup 25162306a36Sopenharmony_ci _asm_extable 31b, .Llarge_fixup 25262306a36Sopenharmony_ci _asm_extable 32b, .Llarge_fixup 25362306a36Sopenharmony_ci _asm_extable 33b, .Llarge_fixup 25462306a36Sopenharmony_ci _asm_extable 34b, .Lexit 25562306a36Sopenharmony_ci _asm_extable 35b, .Lexit 25662306a36Sopenharmony_ci _asm_extable 36b, .Lsmall_fixup 25762306a36Sopenharmony_ci _asm_extable 37b, .Lsmall_fixup 25862306a36Sopenharmony_ci _asm_extable 38b, .Lsmall_fixup 25962306a36Sopenharmony_ci _asm_extable 39b, .Lsmall_fixup 26062306a36Sopenharmony_ci _asm_extable 40b, .Lsmall_fixup 26162306a36Sopenharmony_ci _asm_extable 41b, .Lsmall_fixup 26262306a36Sopenharmony_ci _asm_extable 42b, .Lsmall_fixup 26362306a36Sopenharmony_ci _asm_extable 43b, .Lsmall_fixup 26462306a36Sopenharmony_ci _asm_extable 44b, .Lsmall_fixup 26562306a36Sopenharmony_ci _asm_extable 45b, .Lsmall_fixup 26662306a36Sopenharmony_ci _asm_extable 46b, .Lsmall_fixup 26762306a36Sopenharmony_ci _asm_extable 47b, .Lsmall_fixup 26862306a36Sopenharmony_ci _asm_extable 48b, .Lsmall_fixup 26962306a36Sopenharmony_ci _asm_extable 49b, .Lsmall_fixup 27062306a36Sopenharmony_ci _asm_extable 50b, .Lsmall_fixup 27162306a36Sopenharmony_ci _asm_extable 51b, .Lsmall_fixup 27262306a36Sopenharmony_ci _asm_extable 52b, .Lsmall_fixup 27362306a36Sopenharmony_ci _asm_extable 53b, .Lsmall_fixup 27462306a36Sopenharmony_ci _asm_extable 54b, .Lsmall_fixup 27562306a36Sopenharmony_ci _asm_extable 55b, .Lsmall_fixup 27662306a36Sopenharmony_ci _asm_extable 56b, .Lsmall_fixup 27762306a36Sopenharmony_ci _asm_extable 57b, .Lsmall_fixup 27862306a36Sopenharmony_ci _asm_extable 58b, .Lexit 27962306a36Sopenharmony_ci _asm_extable 59b, .Lexit 28062306a36Sopenharmony_ciSYM_FUNC_END(__copy_user_fast) 281