#include <linux/linkage.h>1#include <linux/export.h>2#include <asm/asm.h>3#include <asm/asm-extable.h>4#include <asm/csr.h>5#include <asm/hwcap.h>6#include <asm/alternative-macros.h>78.macro fixup op reg addr lbl9100:10\op \reg, \addr11_asm_extable 100b, \lbl12.endm1314SYM_FUNC_START(__asm_copy_to_user)15#ifdef CONFIG_RISCV_ISA_V16ALTERNATIVE("j fallback_scalar_usercopy", "nop", 0, RISCV_ISA_EXT_ZVE32X, CONFIG_RISCV_ISA_V)17REG_L t0, riscv_v_usercopy_threshold18bltu a2, t0, fallback_scalar_usercopy19li a3, 120tail enter_vector_usercopy21#endif22SYM_FUNC_END(__asm_copy_to_user)23EXPORT_SYMBOL(__asm_copy_to_user)24SYM_FUNC_ALIAS(__asm_copy_from_user, __asm_copy_to_user)25EXPORT_SYMBOL(__asm_copy_from_user)2627SYM_FUNC_START(fallback_scalar_usercopy)28/* Enable access to user memory */29li t6, SR_SUM30csrs CSR_STATUS, t631mv t6, ra3233call fallback_scalar_usercopy_sum_enabled3435/* Disable access to user memory */36mv ra, t637li t6, SR_SUM38csrc CSR_STATUS, t639ret40SYM_FUNC_END(fallback_scalar_usercopy)4142SYM_FUNC_START(__asm_copy_to_user_sum_enabled)43#ifdef CONFIG_RISCV_ISA_V44ALTERNATIVE("j fallback_scalar_usercopy_sum_enabled", "nop", 0, RISCV_ISA_EXT_ZVE32X, CONFIG_RISCV_ISA_V)45REG_L t0, riscv_v_usercopy_threshold46bltu a2, t0, fallback_scalar_usercopy_sum_enabled47li a3, 048tail enter_vector_usercopy49#endif50SYM_FUNC_END(__asm_copy_to_user_sum_enabled)51SYM_FUNC_ALIAS(__asm_copy_from_user_sum_enabled, __asm_copy_to_user_sum_enabled)52EXPORT_SYMBOL(__asm_copy_from_user_sum_enabled)53EXPORT_SYMBOL(__asm_copy_to_user_sum_enabled)5455SYM_FUNC_START(fallback_scalar_usercopy_sum_enabled)56/*57* Save the terminal address which will be used to compute the number58* of bytes copied in case of a fixup exception.59*/60add t5, a0, a26162/*63* Register allocation for code below:64* a0 - start of uncopied dst65* a1 - start of uncopied src66* a2 - size67* t0 - end of uncopied dst68*/69add t0, a0, a27071/*72* Use byte copy only if too small.73* SZREG holds 4 for RV32 and 8 for RV6474*/75li a3, 9*SZREG-1 /* size must >= (word_copy stride + SZREG-1) */76bltu a2, a3, .Lbyte_copy_tail7778/*79* Copy first bytes until dst is aligned to word boundary.80* a0 - start of dst81* t1 - start of aligned dst82*/83addi t1, a0, SZREG-184andi t1, t1, ~(SZREG-1)85/* dst is already aligned, skip */86beq a0, t1, .Lskip_align_dst871:88/* a5 - one byte for copying data */89fixup lb a5, 0(a1), 10f90addi a1, a1, 1 /* src */91fixup sb a5, 0(a0), 10f92addi a0, a0, 1 /* dst */93bltu a0, t1, 1b /* t1 - start of aligned dst */9495.Lskip_align_dst:96/*97* Now dst is aligned.98* Use shift-copy if src is misaligned.99* Use word-copy if both src and dst are aligned because100* can not use shift-copy which do not require shifting101*/102/* a1 - start of src */103andi a3, a1, SZREG-1104bnez a3, .Lshift_copy105106.Lword_copy:107/*108* Both src and dst are aligned, unrolled word copy109*110* a0 - start of aligned dst111* a1 - start of aligned src112* t0 - end of aligned dst113*/114addi t0, t0, -(8*SZREG) /* not to over run */1152:116fixup REG_L a4, 0(a1), 10f117fixup REG_L a5, SZREG(a1), 10f118fixup REG_L a6, 2*SZREG(a1), 10f119fixup REG_L a7, 3*SZREG(a1), 10f120fixup REG_L t1, 4*SZREG(a1), 10f121fixup REG_L t2, 5*SZREG(a1), 10f122fixup REG_L t3, 6*SZREG(a1), 10f123fixup REG_L t4, 7*SZREG(a1), 10f124fixup REG_S a4, 0(a0), 10f125fixup REG_S a5, SZREG(a0), 10f126fixup REG_S a6, 2*SZREG(a0), 10f127fixup REG_S a7, 3*SZREG(a0), 10f128fixup REG_S t1, 4*SZREG(a0), 10f129fixup REG_S t2, 5*SZREG(a0), 10f130fixup REG_S t3, 6*SZREG(a0), 10f131fixup REG_S t4, 7*SZREG(a0), 10f132addi a0, a0, 8*SZREG133addi a1, a1, 8*SZREG134bleu a0, t0, 2b135136addi t0, t0, 8*SZREG /* revert to original value */137j .Lbyte_copy_tail138139.Lshift_copy:140141/*142* Word copy with shifting.143* For misaligned copy we still perform aligned word copy, but144* we need to use the value fetched from the previous iteration and145* do some shifts.146* This is safe because reading is less than a word size.147*148* a0 - start of aligned dst149* a1 - start of src150* a3 - a1 & mask:(SZREG-1)151* t0 - end of uncopied dst152* t1 - end of aligned dst153*/154/* calculating aligned word boundary for dst */155andi t1, t0, ~(SZREG-1)156/* Converting unaligned src to aligned src */157andi a1, a1, ~(SZREG-1)158159/*160* Calculate shifts161* t3 - prev shift162* t4 - current shift163*/164slli t3, a3, 3 /* converting bytes in a3 to bits */165li a5, SZREG*8166sub t4, a5, t3167168/* Load the first word to combine with second word */169fixup REG_L a5, 0(a1), 10f1701713:172/* Main shifting copy173*174* a0 - start of aligned dst175* a1 - start of aligned src176* t1 - end of aligned dst177*/178179/* At least one iteration will be executed */180srl a4, a5, t3181fixup REG_L a5, SZREG(a1), 10f182addi a1, a1, SZREG183sll a2, a5, t4184or a2, a2, a4185fixup REG_S a2, 0(a0), 10f186addi a0, a0, SZREG187bltu a0, t1, 3b188189/* Revert src to original unaligned value */190add a1, a1, a3191192.Lbyte_copy_tail:193/*194* Byte copy anything left.195*196* a0 - start of remaining dst197* a1 - start of remaining src198* t0 - end of remaining dst199*/200bgeu a0, t0, .Lout_copy_user /* check if end of copy */2014:202fixup lb a5, 0(a1), 10f203addi a1, a1, 1 /* src */204fixup sb a5, 0(a0), 10f205addi a0, a0, 1 /* dst */206bltu a0, t0, 4b /* t0 - end of dst */207208.Lout_copy_user:209li a0, 0210ret21110:212sub a0, t5, a0213ret214SYM_FUNC_END(fallback_scalar_usercopy_sum_enabled)215216SYM_FUNC_START(__clear_user)217218/* Enable access to user memory */219li t6, SR_SUM220csrs CSR_STATUS, t6221222add a3, a0, a1223addi t0, a0, SZREG-1224andi t1, a3, ~(SZREG-1)225andi t0, t0, ~(SZREG-1)226/*227* a3: terminal address of target region228* t0: lowest doubleword-aligned address in target region229* t1: highest doubleword-aligned address in target region230*/231bgeu t0, t1, 2f232bltu a0, t0, 4f2331:234fixup REG_S, zero, (a0), 11f235addi a0, a0, SZREG236bltu a0, t1, 1b2372:238bltu a0, a3, 5f2392403:241/* Disable access to user memory */242csrc CSR_STATUS, t6243li a0, 0244ret2454: /* Edge case: unalignment */246fixup sb, zero, (a0), 11f247addi a0, a0, 1248bltu a0, t0, 4b249j 1b2505: /* Edge case: remainder */251fixup sb, zero, (a0), 11f252addi a0, a0, 1253bltu a0, a3, 5b254j 3b255256/* Exception fixup code */25711:258/* Disable access to user memory */259csrc CSR_STATUS, t6260sub a0, a3, a0261ret262SYM_FUNC_END(__clear_user)263EXPORT_SYMBOL(__clear_user)264265266