2017-07-11 09:03:19 +08:00
|
|
|
#include <linux/linkage.h>
|
|
|
|
#include <asm/asm.h>
|
|
|
|
#include <asm/csr.h>
|
|
|
|
|
|
|
|
.altmacro
|
|
|
|
.macro fixup op reg addr lbl
|
|
|
|
LOCAL _epc
|
|
|
|
_epc:
|
|
|
|
\op \reg, \addr
|
|
|
|
.section __ex_table,"a"
|
|
|
|
.balign RISCV_SZPTR
|
|
|
|
RISCV_PTR _epc, \lbl
|
|
|
|
.previous
|
|
|
|
.endm
|
|
|
|
|
2018-06-09 08:33:51 +08:00
|
|
|
ENTRY(__asm_copy_to_user)
|
|
|
|
ENTRY(__asm_copy_from_user)
|
2017-07-11 09:03:19 +08:00
|
|
|
|
|
|
|
/* Enable access to user memory */
|
|
|
|
li t6, SR_SUM
|
2019-08-08 00:13:38 +08:00
|
|
|
csrs CSR_SSTATUS, t6
|
2017-07-11 09:03:19 +08:00
|
|
|
|
|
|
|
add a3, a1, a2
|
|
|
|
/* Use word-oriented copy only if low-order bits match */
|
|
|
|
andi t0, a0, SZREG-1
|
|
|
|
andi t1, a1, SZREG-1
|
|
|
|
bne t0, t1, 2f
|
|
|
|
|
|
|
|
addi t0, a1, SZREG-1
|
|
|
|
andi t1, a3, ~(SZREG-1)
|
|
|
|
andi t0, t0, ~(SZREG-1)
|
|
|
|
/*
|
|
|
|
* a3: terminal address of source region
|
|
|
|
* t0: lowest XLEN-aligned address in source
|
|
|
|
* t1: highest XLEN-aligned address in source
|
|
|
|
*/
|
|
|
|
bgeu t0, t1, 2f
|
|
|
|
bltu a1, t0, 4f
|
|
|
|
1:
|
|
|
|
fixup REG_L, t2, (a1), 10f
|
|
|
|
fixup REG_S, t2, (a0), 10f
|
|
|
|
addi a1, a1, SZREG
|
|
|
|
addi a0, a0, SZREG
|
|
|
|
bltu a1, t1, 1b
|
|
|
|
2:
|
|
|
|
bltu a1, a3, 5f
|
|
|
|
|
|
|
|
3:
|
|
|
|
/* Disable access to user memory */
|
2019-08-08 00:13:38 +08:00
|
|
|
csrc CSR_SSTATUS, t6
|
2017-07-11 09:03:19 +08:00
|
|
|
li a0, 0
|
|
|
|
ret
|
|
|
|
4: /* Edge case: unalignment */
|
|
|
|
fixup lbu, t2, (a1), 10f
|
|
|
|
fixup sb, t2, (a0), 10f
|
|
|
|
addi a1, a1, 1
|
|
|
|
addi a0, a0, 1
|
|
|
|
bltu a1, t0, 4b
|
|
|
|
j 1b
|
|
|
|
5: /* Edge case: remainder */
|
|
|
|
fixup lbu, t2, (a1), 10f
|
|
|
|
fixup sb, t2, (a0), 10f
|
|
|
|
addi a1, a1, 1
|
|
|
|
addi a0, a0, 1
|
|
|
|
bltu a1, a3, 5b
|
|
|
|
j 3b
|
2018-06-09 08:33:51 +08:00
|
|
|
ENDPROC(__asm_copy_to_user)
|
|
|
|
ENDPROC(__asm_copy_from_user)
|
2017-07-11 09:03:19 +08:00
|
|
|
|
|
|
|
|
|
|
|
ENTRY(__clear_user)
|
|
|
|
|
|
|
|
/* Enable access to user memory */
|
|
|
|
li t6, SR_SUM
|
2019-08-08 00:13:38 +08:00
|
|
|
csrs CSR_SSTATUS, t6
|
2017-07-11 09:03:19 +08:00
|
|
|
|
|
|
|
add a3, a0, a1
|
|
|
|
addi t0, a0, SZREG-1
|
|
|
|
andi t1, a3, ~(SZREG-1)
|
|
|
|
andi t0, t0, ~(SZREG-1)
|
|
|
|
/*
|
|
|
|
* a3: terminal address of target region
|
|
|
|
* t0: lowest doubleword-aligned address in target region
|
|
|
|
* t1: highest doubleword-aligned address in target region
|
|
|
|
*/
|
|
|
|
bgeu t0, t1, 2f
|
|
|
|
bltu a0, t0, 4f
|
|
|
|
1:
|
2018-05-08 10:59:33 +08:00
|
|
|
fixup REG_S, zero, (a0), 11f
|
2017-07-11 09:03:19 +08:00
|
|
|
addi a0, a0, SZREG
|
|
|
|
bltu a0, t1, 1b
|
|
|
|
2:
|
|
|
|
bltu a0, a3, 5f
|
|
|
|
|
|
|
|
3:
|
|
|
|
/* Disable access to user memory */
|
2019-08-08 00:13:38 +08:00
|
|
|
csrc CSR_SSTATUS, t6
|
2017-07-11 09:03:19 +08:00
|
|
|
li a0, 0
|
|
|
|
ret
|
|
|
|
4: /* Edge case: unalignment */
|
2018-05-08 10:59:33 +08:00
|
|
|
fixup sb, zero, (a0), 11f
|
2017-07-11 09:03:19 +08:00
|
|
|
addi a0, a0, 1
|
|
|
|
bltu a0, t0, 4b
|
|
|
|
j 1b
|
|
|
|
5: /* Edge case: remainder */
|
2018-05-08 10:59:33 +08:00
|
|
|
fixup sb, zero, (a0), 11f
|
2017-07-11 09:03:19 +08:00
|
|
|
addi a0, a0, 1
|
|
|
|
bltu a0, a3, 5b
|
|
|
|
j 3b
|
|
|
|
ENDPROC(__clear_user)
|
|
|
|
|
|
|
|
.section .fixup,"ax"
|
|
|
|
.balign 4
|
2018-05-08 10:59:33 +08:00
|
|
|
/* Fixup code for __copy_user(10) and __clear_user(11) */
|
2017-07-11 09:03:19 +08:00
|
|
|
10:
|
|
|
|
/* Disable access to user memory */
|
2019-08-08 00:13:38 +08:00
|
|
|
csrs CSR_SSTATUS, t6
|
2018-05-08 10:59:33 +08:00
|
|
|
mv a0, a2
|
|
|
|
ret
|
|
|
|
11:
|
2019-08-08 00:13:38 +08:00
|
|
|
csrs CSR_SSTATUS, t6
|
2018-05-08 10:59:33 +08:00
|
|
|
mv a0, a1
|
2017-07-11 09:03:19 +08:00
|
|
|
ret
|
|
|
|
.previous
|