/*1* arch/alpha/lib/copy_user.S2*3* Copy to/from user space, handling exceptions as we go.. This4* isn't exactly pretty.5*6* This is essentially the same as "memcpy()", but with a few twists.7* Notably, we have to make sure that $0 is always up-to-date and8* contains the right "bytes left to copy" value (and that it is updated9* only _after_ a successful copy). There is also some rather minor10* exception setup stuff..11*12* NOTE! This is not directly C-callable, because the calling semantics are13* different:14*15* Inputs:16* length in $017* destination address in $618* source address in $719* return address in $2820*21* Outputs:22* bytes left to copy in $023*24* Clobbers:25* $1,$2,$3,$4,$5,$6,$726*/2728/* Allow an exception for an insn; exit if we get one. */29#define EXI(x,y...) \3099: x,##y; \31.section __ex_table,"a"; \32.long 99b - .; \33lda $31, $exitin-99b($31); \34.previous3536#define EXO(x,y...) \3799: x,##y; \38.section __ex_table,"a"; \39.long 99b - .; \40lda $31, $exitout-99b($31); \41.previous4243.set noat44.align 445.globl __copy_user46.ent __copy_user47__copy_user:48.prologue 049and $6,7,$350beq $0,$3551beq $3,$3652subq $3,8,$353.align 454$37:55EXI( ldq_u $1,0($7) )56EXO( ldq_u $2,0($6) )57extbl $1,$7,$158mskbl $2,$6,$259insbl $1,$6,$160addq $3,1,$361bis $1,$2,$162EXO( stq_u $1,0($6) )63subq $0,1,$064addq $6,1,$665addq $7,1,$766beq $0,$4167bne $3,$3768$36:69and $7,7,$170bic $0,7,$471beq $1,$4372beq $4,$4873EXI( ldq_u $3,0($7) )74.align 475$50:76EXI( ldq_u $2,8($7) )77subq $4,8,$478extql $3,$7,$379extqh $2,$7,$180bis $3,$1,$181EXO( stq $1,0($6) )82addq $7,8,$783subq $0,8,$084addq $6,8,$685bis $2,$2,$386bne $4,$5087$48:88beq $0,$4189.align 490$57:91EXI( ldq_u $1,0($7) )92EXO( ldq_u $2,0($6) )93extbl $1,$7,$194mskbl $2,$6,$295insbl $1,$6,$196bis $1,$2,$197EXO( stq_u $1,0($6) )98subq $0,1,$099addq $6,1,$6100addq $7,1,$7101bne $0,$57102br $31,$41103.align 4104$43:105beq $4,$65106.align 4107$66:108EXI( ldq $1,0($7) )109subq $4,8,$4110EXO( stq $1,0($6) )111addq $7,8,$7112subq $0,8,$0113addq $6,8,$6114bne $4,$66115$65:116beq $0,$41117EXI( ldq $2,0($7) )118EXO( ldq $1,0($6) )119mskql $2,$0,$2120mskqh $1,$0,$1121bis $2,$1,$2122EXO( stq $2,0($6) )123bis $31,$31,$0124$41:125$35:126$exitout:127ret $31,($28),1128129$exitin:130/* A stupid byte-by-byte zeroing of the rest of the output131buffer. This cures security holes by never leaving132random kernel data around to be copied elsewhere. */133134mov $0,$1135$101:136EXO ( ldq_u $2,0($6) )137subq $1,1,$1138mskbl $2,$6,$2139EXO ( stq_u $2,0($6) )140addq $6,1,$6141bgt $1,$101142ret $31,($28),1143144.end __copy_user145146147