diff options
Diffstat (limited to 'arch/alpha/lib/copy_user.S')
-rw-r--r-- | arch/alpha/lib/copy_user.S | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/arch/alpha/lib/copy_user.S b/arch/alpha/lib/copy_user.S new file mode 100644 index 000000000000..6f3fab9eb434 --- /dev/null +++ b/arch/alpha/lib/copy_user.S | |||
@@ -0,0 +1,145 @@ | |||
1 | /* | ||
2 | * arch/alpha/lib/copy_user.S | ||
3 | * | ||
4 | * Copy to/from user space, handling exceptions as we go.. This | ||
5 | * isn't exactly pretty. | ||
6 | * | ||
7 | * This is essentially the same as "memcpy()", but with a few twists. | ||
8 | * Notably, we have to make sure that $0 is always up-to-date and | ||
9 | * contains the right "bytes left to copy" value (and that it is updated | ||
10 | * only _after_ a successful copy). There is also some rather minor | ||
11 | * exception setup stuff.. | ||
12 | * | ||
13 | * NOTE! This is not directly C-callable, because the calling semantics are | ||
14 | * different: | ||
15 | * | ||
16 | * Inputs: | ||
17 | * length in $0 | ||
18 | * destination address in $6 | ||
19 | * source address in $7 | ||
20 | * return address in $28 | ||
21 | * | ||
22 | * Outputs: | ||
23 | * bytes left to copy in $0 | ||
24 | * | ||
25 | * Clobbers: | ||
26 | * $1,$2,$3,$4,$5,$6,$7 | ||
27 | */ | ||
28 | |||
29 | /* Allow an exception for an insn; exit if we get one. */ | ||
30 | #define EXI(x,y...) \ | ||
31 | 99: x,##y; \ | ||
32 | .section __ex_table,"a"; \ | ||
33 | .long 99b - .; \ | ||
34 | lda $31, $exitin-99b($31); \ | ||
35 | .previous | ||
36 | |||
37 | #define EXO(x,y...) \ | ||
38 | 99: x,##y; \ | ||
39 | .section __ex_table,"a"; \ | ||
40 | .long 99b - .; \ | ||
41 | lda $31, $exitout-99b($31); \ | ||
42 | .previous | ||
43 | |||
44 | .set noat | ||
45 | .align 4 | ||
46 | .globl __copy_user | ||
47 | .ent __copy_user | ||
48 | __copy_user: | ||
49 | .prologue 0 | ||
50 | and $6,7,$3 | ||
51 | beq $0,$35 | ||
52 | beq $3,$36 | ||
53 | subq $3,8,$3 | ||
54 | .align 4 | ||
55 | $37: | ||
56 | EXI( ldq_u $1,0($7) ) | ||
57 | EXO( ldq_u $2,0($6) ) | ||
58 | extbl $1,$7,$1 | ||
59 | mskbl $2,$6,$2 | ||
60 | insbl $1,$6,$1 | ||
61 | addq $3,1,$3 | ||
62 | bis $1,$2,$1 | ||
63 | EXO( stq_u $1,0($6) ) | ||
64 | subq $0,1,$0 | ||
65 | addq $6,1,$6 | ||
66 | addq $7,1,$7 | ||
67 | beq $0,$41 | ||
68 | bne $3,$37 | ||
69 | $36: | ||
70 | and $7,7,$1 | ||
71 | bic $0,7,$4 | ||
72 | beq $1,$43 | ||
73 | beq $4,$48 | ||
74 | EXI( ldq_u $3,0($7) ) | ||
75 | .align 4 | ||
76 | $50: | ||
77 | EXI( ldq_u $2,8($7) ) | ||
78 | subq $4,8,$4 | ||
79 | extql $3,$7,$3 | ||
80 | extqh $2,$7,$1 | ||
81 | bis $3,$1,$1 | ||
82 | EXO( stq $1,0($6) ) | ||
83 | addq $7,8,$7 | ||
84 | subq $0,8,$0 | ||
85 | addq $6,8,$6 | ||
86 | bis $2,$2,$3 | ||
87 | bne $4,$50 | ||
88 | $48: | ||
89 | beq $0,$41 | ||
90 | .align 4 | ||
91 | $57: | ||
92 | EXI( ldq_u $1,0($7) ) | ||
93 | EXO( ldq_u $2,0($6) ) | ||
94 | extbl $1,$7,$1 | ||
95 | mskbl $2,$6,$2 | ||
96 | insbl $1,$6,$1 | ||
97 | bis $1,$2,$1 | ||
98 | EXO( stq_u $1,0($6) ) | ||
99 | subq $0,1,$0 | ||
100 | addq $6,1,$6 | ||
101 | addq $7,1,$7 | ||
102 | bne $0,$57 | ||
103 | br $31,$41 | ||
104 | .align 4 | ||
105 | $43: | ||
106 | beq $4,$65 | ||
107 | .align 4 | ||
108 | $66: | ||
109 | EXI( ldq $1,0($7) ) | ||
110 | subq $4,8,$4 | ||
111 | EXO( stq $1,0($6) ) | ||
112 | addq $7,8,$7 | ||
113 | subq $0,8,$0 | ||
114 | addq $6,8,$6 | ||
115 | bne $4,$66 | ||
116 | $65: | ||
117 | beq $0,$41 | ||
118 | EXI( ldq $2,0($7) ) | ||
119 | EXO( ldq $1,0($6) ) | ||
120 | mskql $2,$0,$2 | ||
121 | mskqh $1,$0,$1 | ||
122 | bis $2,$1,$2 | ||
123 | EXO( stq $2,0($6) ) | ||
124 | bis $31,$31,$0 | ||
125 | $41: | ||
126 | $35: | ||
127 | $exitout: | ||
128 | ret $31,($28),1 | ||
129 | |||
130 | $exitin: | ||
131 | /* A stupid byte-by-byte zeroing of the rest of the output | ||
132 | buffer. This cures security holes by never leaving | ||
133 | random kernel data around to be copied elsewhere. */ | ||
134 | |||
135 | mov $0,$1 | ||
136 | $101: | ||
137 | EXO ( ldq_u $2,0($6) ) | ||
138 | subq $1,1,$1 | ||
139 | mskbl $2,$6,$2 | ||
140 | EXO ( stq_u $2,0($6) ) | ||
141 | addq $6,1,$6 | ||
142 | bgt $1,$101 | ||
143 | ret $31,($28),1 | ||
144 | |||
145 | .end __copy_user | ||