125 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			125 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
#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
 | 
						|
 | 
						|
ENTRY(__asm_copy_to_user)
 | 
						|
ENTRY(__asm_copy_from_user)
 | 
						|
 | 
						|
	/* Enable access to user memory */
 | 
						|
	li t6, SR_SUM
 | 
						|
	csrs sstatus, t6
 | 
						|
 | 
						|
	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 */
 | 
						|
	csrc sstatus, t6
 | 
						|
	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
 | 
						|
ENDPROC(__asm_copy_to_user)
 | 
						|
ENDPROC(__asm_copy_from_user)
 | 
						|
 | 
						|
 | 
						|
ENTRY(__clear_user)
 | 
						|
 | 
						|
	/* Enable access to user memory */
 | 
						|
	li t6, SR_SUM
 | 
						|
	csrs sstatus, t6
 | 
						|
 | 
						|
	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:
 | 
						|
	fixup REG_S, zero, (a0), 11f
 | 
						|
	addi a0, a0, SZREG
 | 
						|
	bltu a0, t1, 1b
 | 
						|
2:
 | 
						|
	bltu a0, a3, 5f
 | 
						|
 | 
						|
3:
 | 
						|
	/* Disable access to user memory */
 | 
						|
	csrc sstatus, t6
 | 
						|
	li a0, 0
 | 
						|
	ret
 | 
						|
4: /* Edge case: unalignment */
 | 
						|
	fixup sb, zero, (a0), 11f
 | 
						|
	addi a0, a0, 1
 | 
						|
	bltu a0, t0, 4b
 | 
						|
	j 1b
 | 
						|
5: /* Edge case: remainder */
 | 
						|
	fixup sb, zero, (a0), 11f
 | 
						|
	addi a0, a0, 1
 | 
						|
	bltu a0, a3, 5b
 | 
						|
	j 3b
 | 
						|
ENDPROC(__clear_user)
 | 
						|
 | 
						|
	.section .fixup,"ax"
 | 
						|
	.balign 4
 | 
						|
	/* Fixup code for __copy_user(10) and __clear_user(11) */
 | 
						|
10:
 | 
						|
	/* Disable access to user memory */
 | 
						|
	csrs sstatus, t6
 | 
						|
	mv a0, a2
 | 
						|
	ret
 | 
						|
11:
 | 
						|
	csrs sstatus, t6
 | 
						|
	mv a0, a1
 | 
						|
	ret
 | 
						|
	.previous
 |