123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- /*
- * arch/alpha/lib/copy_user.S
- *
- * Copy to/from user space, handling exceptions as we go.. This
- * isn't exactly pretty.
- *
- * This is essentially the same as "memcpy()", but with a few twists.
- * Notably, we have to make sure that $0 is always up-to-date and
- * contains the right "bytes left to copy" value (and that it is updated
- * only _after_ a successful copy). There is also some rather minor
- * exception setup stuff..
- *
- * NOTE! This is not directly C-callable, because the calling semantics are
- * different:
- *
- * Inputs:
- * length in $0
- * destination address in $6
- * source address in $7
- * return address in $28
- *
- * Outputs:
- * bytes left to copy in $0
- *
- * Clobbers:
- * $1,$2,$3,$4,$5,$6,$7
- */
- /* Allow an exception for an insn; exit if we get one. */
- #define EXI(x,y...) \
- 99: x,##y; \
- .section __ex_table,"a"; \
- .long 99b - .; \
- lda $31, $exitin-99b($31); \
- .previous
- #define EXO(x,y...) \
- 99: x,##y; \
- .section __ex_table,"a"; \
- .long 99b - .; \
- lda $31, $exitout-99b($31); \
- .previous
- .set noat
- .align 4
- .globl __copy_user
- .ent __copy_user
- __copy_user:
- .prologue 0
- and $6,7,$3
- beq $0,$35
- beq $3,$36
- subq $3,8,$3
- .align 4
- $37:
- EXI( ldq_u $1,0($7) )
- EXO( ldq_u $2,0($6) )
- extbl $1,$7,$1
- mskbl $2,$6,$2
- insbl $1,$6,$1
- addq $3,1,$3
- bis $1,$2,$1
- EXO( stq_u $1,0($6) )
- subq $0,1,$0
- addq $6,1,$6
- addq $7,1,$7
- beq $0,$41
- bne $3,$37
- $36:
- and $7,7,$1
- bic $0,7,$4
- beq $1,$43
- beq $4,$48
- EXI( ldq_u $3,0($7) )
- .align 4
- $50:
- EXI( ldq_u $2,8($7) )
- subq $4,8,$4
- extql $3,$7,$3
- extqh $2,$7,$1
- bis $3,$1,$1
- EXO( stq $1,0($6) )
- addq $7,8,$7
- subq $0,8,$0
- addq $6,8,$6
- bis $2,$2,$3
- bne $4,$50
- $48:
- beq $0,$41
- .align 4
- $57:
- EXI( ldq_u $1,0($7) )
- EXO( ldq_u $2,0($6) )
- extbl $1,$7,$1
- mskbl $2,$6,$2
- insbl $1,$6,$1
- bis $1,$2,$1
- EXO( stq_u $1,0($6) )
- subq $0,1,$0
- addq $6,1,$6
- addq $7,1,$7
- bne $0,$57
- br $31,$41
- .align 4
- $43:
- beq $4,$65
- .align 4
- $66:
- EXI( ldq $1,0($7) )
- subq $4,8,$4
- EXO( stq $1,0($6) )
- addq $7,8,$7
- subq $0,8,$0
- addq $6,8,$6
- bne $4,$66
- $65:
- beq $0,$41
- EXI( ldq $2,0($7) )
- EXO( ldq $1,0($6) )
- mskql $2,$0,$2
- mskqh $1,$0,$1
- bis $2,$1,$2
- EXO( stq $2,0($6) )
- bis $31,$31,$0
- $41:
- $35:
- $exitout:
- ret $31,($28),1
- $exitin:
- /* A stupid byte-by-byte zeroing of the rest of the output
- buffer. This cures security holes by never leaving
- random kernel data around to be copied elsewhere. */
- mov $0,$1
- $101:
- EXO ( ldq_u $2,0($6) )
- subq $1,1,$1
- mskbl $2,$6,$2
- EXO ( stq_u $2,0($6) )
- addq $6,1,$6
- bgt $1,$101
- ret $31,($28),1
- .end __copy_user
|