1*4882a593Smuzhiyun#include <linux/linkage.h> 2*4882a593Smuzhiyun#include <asm-generic/export.h> 3*4882a593Smuzhiyun#include <asm/asm.h> 4*4882a593Smuzhiyun#include <asm/csr.h> 5*4882a593Smuzhiyun 6*4882a593Smuzhiyun .macro fixup op reg addr lbl 7*4882a593Smuzhiyun100: 8*4882a593Smuzhiyun \op \reg, \addr 9*4882a593Smuzhiyun .section __ex_table,"a" 10*4882a593Smuzhiyun .balign RISCV_SZPTR 11*4882a593Smuzhiyun RISCV_PTR 100b, \lbl 12*4882a593Smuzhiyun .previous 13*4882a593Smuzhiyun .endm 14*4882a593Smuzhiyun 15*4882a593SmuzhiyunENTRY(__asm_copy_to_user) 16*4882a593SmuzhiyunENTRY(__asm_copy_from_user) 17*4882a593Smuzhiyun 18*4882a593Smuzhiyun /* Enable access to user memory */ 19*4882a593Smuzhiyun li t6, SR_SUM 20*4882a593Smuzhiyun csrs CSR_STATUS, t6 21*4882a593Smuzhiyun 22*4882a593Smuzhiyun add a3, a1, a2 23*4882a593Smuzhiyun /* Use word-oriented copy only if low-order bits match */ 24*4882a593Smuzhiyun andi t0, a0, SZREG-1 25*4882a593Smuzhiyun andi t1, a1, SZREG-1 26*4882a593Smuzhiyun bne t0, t1, 2f 27*4882a593Smuzhiyun 28*4882a593Smuzhiyun addi t0, a1, SZREG-1 29*4882a593Smuzhiyun andi t1, a3, ~(SZREG-1) 30*4882a593Smuzhiyun andi t0, t0, ~(SZREG-1) 31*4882a593Smuzhiyun /* 32*4882a593Smuzhiyun * a3: terminal address of source region 33*4882a593Smuzhiyun * t0: lowest XLEN-aligned address in source 34*4882a593Smuzhiyun * t1: highest XLEN-aligned address in source 35*4882a593Smuzhiyun */ 36*4882a593Smuzhiyun bgeu t0, t1, 2f 37*4882a593Smuzhiyun bltu a1, t0, 4f 38*4882a593Smuzhiyun1: 39*4882a593Smuzhiyun fixup REG_L, t2, (a1), 10f 40*4882a593Smuzhiyun fixup REG_S, t2, (a0), 10f 41*4882a593Smuzhiyun addi a1, a1, SZREG 42*4882a593Smuzhiyun addi a0, a0, SZREG 43*4882a593Smuzhiyun bltu a1, t1, 1b 44*4882a593Smuzhiyun2: 45*4882a593Smuzhiyun bltu a1, a3, 5f 46*4882a593Smuzhiyun 47*4882a593Smuzhiyun3: 48*4882a593Smuzhiyun /* Disable access to user memory */ 49*4882a593Smuzhiyun csrc CSR_STATUS, t6 50*4882a593Smuzhiyun li a0, 0 51*4882a593Smuzhiyun ret 52*4882a593Smuzhiyun4: /* Edge case: unalignment */ 53*4882a593Smuzhiyun fixup lbu, t2, (a1), 10f 54*4882a593Smuzhiyun fixup sb, t2, (a0), 10f 55*4882a593Smuzhiyun addi a1, a1, 1 56*4882a593Smuzhiyun addi a0, a0, 1 57*4882a593Smuzhiyun bltu a1, t0, 4b 58*4882a593Smuzhiyun j 1b 59*4882a593Smuzhiyun5: /* Edge case: remainder */ 60*4882a593Smuzhiyun fixup lbu, t2, (a1), 10f 61*4882a593Smuzhiyun fixup sb, t2, (a0), 10f 62*4882a593Smuzhiyun addi a1, a1, 1 63*4882a593Smuzhiyun addi a0, a0, 1 64*4882a593Smuzhiyun bltu a1, a3, 5b 65*4882a593Smuzhiyun j 3b 66*4882a593SmuzhiyunENDPROC(__asm_copy_to_user) 67*4882a593SmuzhiyunENDPROC(__asm_copy_from_user) 68*4882a593SmuzhiyunEXPORT_SYMBOL(__asm_copy_to_user) 69*4882a593SmuzhiyunEXPORT_SYMBOL(__asm_copy_from_user) 70*4882a593Smuzhiyun 71*4882a593Smuzhiyun 72*4882a593SmuzhiyunENTRY(__clear_user) 73*4882a593Smuzhiyun 74*4882a593Smuzhiyun /* Enable access to user memory */ 75*4882a593Smuzhiyun li t6, SR_SUM 76*4882a593Smuzhiyun csrs CSR_STATUS, t6 77*4882a593Smuzhiyun 78*4882a593Smuzhiyun add a3, a0, a1 79*4882a593Smuzhiyun addi t0, a0, SZREG-1 80*4882a593Smuzhiyun andi t1, a3, ~(SZREG-1) 81*4882a593Smuzhiyun andi t0, t0, ~(SZREG-1) 82*4882a593Smuzhiyun /* 83*4882a593Smuzhiyun * a3: terminal address of target region 84*4882a593Smuzhiyun * t0: lowest doubleword-aligned address in target region 85*4882a593Smuzhiyun * t1: highest doubleword-aligned address in target region 86*4882a593Smuzhiyun */ 87*4882a593Smuzhiyun bgeu t0, t1, 2f 88*4882a593Smuzhiyun bltu a0, t0, 4f 89*4882a593Smuzhiyun1: 90*4882a593Smuzhiyun fixup REG_S, zero, (a0), 11f 91*4882a593Smuzhiyun addi a0, a0, SZREG 92*4882a593Smuzhiyun bltu a0, t1, 1b 93*4882a593Smuzhiyun2: 94*4882a593Smuzhiyun bltu a0, a3, 5f 95*4882a593Smuzhiyun 96*4882a593Smuzhiyun3: 97*4882a593Smuzhiyun /* Disable access to user memory */ 98*4882a593Smuzhiyun csrc CSR_STATUS, t6 99*4882a593Smuzhiyun li a0, 0 100*4882a593Smuzhiyun ret 101*4882a593Smuzhiyun4: /* Edge case: unalignment */ 102*4882a593Smuzhiyun fixup sb, zero, (a0), 11f 103*4882a593Smuzhiyun addi a0, a0, 1 104*4882a593Smuzhiyun bltu a0, t0, 4b 105*4882a593Smuzhiyun j 1b 106*4882a593Smuzhiyun5: /* Edge case: remainder */ 107*4882a593Smuzhiyun fixup sb, zero, (a0), 11f 108*4882a593Smuzhiyun addi a0, a0, 1 109*4882a593Smuzhiyun bltu a0, a3, 5b 110*4882a593Smuzhiyun j 3b 111*4882a593SmuzhiyunENDPROC(__clear_user) 112*4882a593SmuzhiyunEXPORT_SYMBOL(__clear_user) 113*4882a593Smuzhiyun 114*4882a593Smuzhiyun .section .fixup,"ax" 115*4882a593Smuzhiyun .balign 4 116*4882a593Smuzhiyun /* Fixup code for __copy_user(10) and __clear_user(11) */ 117*4882a593Smuzhiyun10: 118*4882a593Smuzhiyun /* Disable access to user memory */ 119*4882a593Smuzhiyun csrs CSR_STATUS, t6 120*4882a593Smuzhiyun mv a0, a2 121*4882a593Smuzhiyun ret 122*4882a593Smuzhiyun11: 123*4882a593Smuzhiyun csrs CSR_STATUS, t6 124*4882a593Smuzhiyun mv a0, a1 125*4882a593Smuzhiyun ret 126*4882a593Smuzhiyun .previous 127