6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #pragma ident "%Z%%M% %I% %E% SMI"
27
28 #include <sys/param.h>
29 #include <sys/errno.h>
30 #include <sys/asm_linkage.h>
31 #include <sys/vtrace.h>
32 #include <sys/machthread.h>
33 #include <sys/clock.h>
34 #include <sys/asi.h>
35 #include <sys/fsr.h>
36 #include <sys/privregs.h>
37
38 #if !defined(lint)
39 #include "assym.h"
40 #endif /* lint */
41
42 /*
43 * Error barrier:
44 * We use membar sync to establish an error barrier for
45 * deferred errors. Membar syncs are added before any update
46 * to t_lofault to ensure that deferred errors from earlier
47 * accesses will not be reported after the membar. This error
48 * isolation is important when we try to recover from async
49 * errors which tries to distinguish kernel accesses to user
50 * data.
51 */
52
53 /*
54 * Copy a null terminated string from one point to another in
55 * the kernel address space.
56 * NOTE - don't use %o5 in this routine as copy{in,out}str uses it.
57 *
58 * copystr(from, to, maxlength, lencopied)
59 * caddr_t from, to;
60 * u_int maxlength, *lencopied;
61 */
62
63 #if defined(lint)
64
65 /* ARGSUSED */
66 int
67 copystr(const char *from, char *to, size_t maxlength, size_t *lencopied)
68 { return(0); }
69
70 #else /* lint */
71
72 ENTRY(copystr)
73 orcc %o2, %g0, %o4 ! save original count
74 bg,a %ncc, 1f
75 sub %o0, %o1, %o0 ! o0 gets the difference of src and dst
76
77 !
78 ! maxlength <= 0
79 !
80 bz %ncc, .cs_out ! maxlength = 0
81 mov ENAMETOOLONG, %o0
82
83 b 2f ! maxlength < 0
84 mov EFAULT, %o0 ! return failure
85
86 !
87 ! Do a byte by byte loop.
88 ! We do this instead of a word by word copy because most strings
89 ! are small and this takes a small number of cache lines.
90 !
91 0:
96
97 ba,pt %ncc, .cs_out ! last byte in string
98 mov 0, %o0 ! ret code = 0
99 1:
100 subcc %o2, 1, %o2 ! test count
101 bgeu,a %ncc, 0b
102 ldub [%o0 + %o1], %g1 ! delay slot, get source byte
103
104 mov 0, %o2 ! max number of bytes moved
105 mov ENAMETOOLONG, %o0 ! ret code = ENAMETOOLONG
106 .cs_out:
107 tst %o3
108 bz %ncc, 2f
109 sub %o4, %o2, %o4 ! compute length and store it
110 stn %o4, [%o3]
111 2:
112 retl
113 nop
114 SET_SIZE(copystr)
115
116 #endif /* lint */
117
118
119 /*
120 * Copy a null terminated string from the user address space into
121 * the kernel address space.
122 */
123 #if defined(lint)
124
125 /* ARGSUSED */
126 int
127 copyinstr(const char *uaddr, char *kaddr, size_t maxlength,
128 size_t *lencopied)
129 { return (0); }
130
131 #else /* lint */
132
133 ENTRY(copyinstr)
134 sethi %hi(.copyinstr_err), %o4
135 ldn [THREAD_REG + T_LOFAULT], %o5 ! catch faults
136 or %o4, %lo(.copyinstr_err), %o4
137 membar #Sync ! sync error barrier
138 stn %o4, [THREAD_REG + T_LOFAULT]
139
140 brz,a,pn %o2, .copyinstr_out
141 mov ENAMETOOLONG, %o0
142
143 mov %o2, %g3 ! g3 is the current count
144 mov %o1, %g4 ! g4 is the dest addr
145
146 b 1f
147 sub %o0, %o1, %g2 ! g2 gets the difference of src and dst
148
149 !
150 ! Do a byte by byte loop.
151 ! We do this instead of a word by word copy because most strings
152 ! are small and this takes a small number of cache lines.
177 stn %o5, [THREAD_REG + T_LOFAULT]
178 ldn [THREAD_REG + T_COPYOPS], %o4
179 brz %o4, 1f
180 nop
181 ldn [%o4 + CP_COPYINSTR], %g1
182 jmp %g1
183 nop
184 1:
185 retl
186 mov EFAULT, %o0
187 .copyinstr_out:
188 tst %o3 ! want length?
189 bz %ncc, 2f
190 sub %o2, %g3, %o2 ! compute length and store it
191 stn %o2, [%o3]
192 2:
193 membar #Sync ! sync error barrier
194 retl
195 stn %o5, [THREAD_REG + T_LOFAULT] ! stop catching faults
196 SET_SIZE(copyinstr)
197 #endif
198
199 #if defined(lint)
200
201 /* ARGSUSED */
202 int
203 copyinstr_noerr(const char *uaddr, char *kaddr, size_t maxlength,
204 size_t *lencopied)
205 { return (0); }
206
207 #else /* lint */
208
209 ENTRY(copyinstr_noerr)
210 mov %o2, %o4 ! save original count
211
212 ! maxlength is unsigned so the only error is if it's 0
213 brz,a,pn %o2, .copyinstr_noerr_out
214 mov ENAMETOOLONG, %o0
215
216 b 1f
217 sub %o0, %o1, %o0 ! o0 gets the difference of src and dst
218
219 !
220 ! Do a byte by byte loop.
221 ! We do this instead of a word by word copy because most strings
222 ! are small and this takes a small number of cache lines.
223 !
224 0:
225 stb %g1, [%o1] ! store byte
226 tst %g1 ! null byte?
227 bnz 1f
228 add %o1, 1, %o1 ! incr dst addr
230 ba,pt %ncc, .copyinstr_noerr_out ! last byte in string
231 mov 0, %o0 ! ret code = 0
232 1:
233 subcc %o2, 1, %o2 ! test count
234 bgeu,a %ncc, 0b
235 lduba [%o0 + %o1]ASI_USER, %g1 ! delay slot, get source byte
236
237 mov 0, %o2 ! max number of bytes moved
238 b .copyinstr_noerr_out
239 mov ENAMETOOLONG, %o0 ! ret code = ENAMETOOLONG
240 .copyinstr_noerr_out:
241 tst %o3 ! want length?
242 bz %ncc, 2f
243 sub %o4, %o2, %o4
244 stn %o4, [%o3]
245 2:
246 retl
247 nop
248 SET_SIZE(copyinstr_noerr)
249
250 #endif /* lint */
251
252 /*
253 * Copy a null terminated string from the kernel
254 * address space to the user address space.
255 */
256
257 #if defined(lint)
258
259 /* ARGSUSED */
260 int
261 copyoutstr(const char *kaddr, char *uaddr, size_t maxlength,
262 size_t *lencopied)
263 { return (0); }
264
265 #else /* lint */
266
267 ENTRY(copyoutstr)
268 sethi %hi(.copyoutstr_err), %o5
269 ldn [THREAD_REG + T_LOFAULT], %o4 ! catch faults
270 or %o5, %lo(.copyoutstr_err), %o5
271 membar #Sync ! sync error barrier
272 stn %o5, [THREAD_REG + T_LOFAULT]
273 mov %o4, %o5
274
275 brz,a,pn %o2, .copyoutstr_out
276 mov ENAMETOOLONG, %o0
277
278 mov %o2, %g3 ! g3 is the current count
279 mov %o1, %g4 ! g4 is the dest addr
280
281 b 1f
282 sub %o0, %o1, %g2 ! g2 gets the difference of src and dst
283
284 !
285 ! Do a byte by byte loop.
286 ! We do this instead of a word by word copy because most strings
313 ldn [THREAD_REG + T_COPYOPS], %o4
314 brz %o4, 1f
315 nop
316 ldn [%o4 + CP_COPYOUTSTR], %g1
317 jmp %g1
318 nop
319 1:
320 retl
321 mov EFAULT, %o0
322 .copyoutstr_out:
323 tst %o3 ! want length?
324 bz %ncc, 2f
325 sub %o2, %g3, %o2 ! compute length and store it
326 stn %o2, [%o3]
327 2:
328 membar #Sync ! sync error barrier
329 retl
330 stn %o5, [THREAD_REG + T_LOFAULT] ! stop catching faults
331 SET_SIZE(copyoutstr)
332
333 #endif /* lint */
334
335 #if defined(lint)
336
337 /* ARGSUSED */
338 int
339 copyoutstr_noerr(const char *kaddr, char *uaddr, size_t maxlength,
340 size_t *lencopied)
341 { return (0); }
342
343 #else /* lint */
344
345 ENTRY(copyoutstr_noerr)
346 mov %o2, %o4 ! save original count
347
348 brz,a,pn %o2, .copyoutstr_noerr_out
349 mov ENAMETOOLONG, %o0
350
351 b 1f
352 sub %o0, %o1, %o0 ! o0 gets the difference of src and dst
353
354 !
355 ! Do a byte by byte loop.
356 ! We do this instead of a word by word copy because most strings
357 ! are small and this takes a small number of cache lines.
358 !
359 0:
360 stba %g1, [%o1]ASI_USER ! store byte
361 tst %g1 ! null byte?
362 bnz 1f
363 add %o1, 1, %o1 ! incr dst addr
364
365 b .copyoutstr_noerr_out ! last byte in string
366 mov 0, %o0 ! ret code = 0
367 1:
368 subcc %o2, 1, %o2 ! test count
369 bgeu,a %ncc, 0b
370 ldub [%o0+%o1], %g1 ! delay slot, get source byte
371
372 mov 0, %o2 ! max number of bytes moved
373 b .copyoutstr_noerr_out
374 mov ENAMETOOLONG, %o0 ! ret code = ENAMETOOLONG
375 .copyoutstr_noerr_out:
376 tst %o3 ! want length?
377 bz %ncc, 2f
378 sub %o4, %o2, %o4
379 stn %o4, [%o3]
380 2:
381 retl
382 nop
383 SET_SIZE(copyoutstr_noerr)
384
385 #endif /* lint */
386
387
388 /*
389 * Copy a block of storage. If the source and target regions overlap,
390 * one or both of the regions will be silently corrupted.
391 * No fault handler installed (to be called under on_fault())
392 */
393
394 #if defined(lint)
395
396 /* ARGSUSED */
397 void
398 ucopy(const void *ufrom, void *uto, size_t ulength)
399 {}
400
401 #else /* lint */
402
403 ENTRY(ucopy)
404 save %sp, -SA(MINFRAME), %sp ! get another window
405
406 subcc %g0, %i2, %i3
407 add %i0, %i2, %i0
408 bz,pn %ncc, 5f
409 add %i1, %i2, %i1
410 lduba [%i0 + %i3]ASI_USER, %i4
411 4: stba %i4, [%i1 + %i3]ASI_USER
412 inccc %i3
413 bcc,a,pt %ncc, 4b
414 lduba [%i0 + %i3]ASI_USER, %i4
415 5:
416 ret
417 restore %g0, 0, %o0 ! return (0)
418
419 SET_SIZE(ucopy)
420 #endif /* lint */
421
422 /*
423 * Copy a user-land string. If the source and target regions overlap,
424 * one or both of the regions will be silently corrupted.
425 * No fault handler installed (to be called under on_fault())
426 */
427
428 #if defined(lint)
429
430 /* ARGSUSED */
431 void
432 ucopystr(const char *ufrom, char *uto, size_t umaxlength, size_t *ulencopied)
433 {}
434
435 #else /* lint */
436
437 ENTRY(ucopystr)
438 save %sp, -SA(MINFRAME), %sp ! get another window
439
440 brz %i2, 5f
441 clr %i5
442
443 lduba [%i0 + %i5]ASI_USER, %i4
444 4: stba %i4, [%i1 + %i5]ASI_USER
445 brz,pn %i4, 5f
446 inc %i5
447 deccc %i2
448 bnz,a,pt %ncc, 4b
449 lduba [%i0 + %i5]ASI_USER, %i4
450 5:
451 brnz,a,pt %i3, 6f
452 stn %i5, [%i3]
453 6:
454 ret
455 restore %g0, 0, %o0 ! return (0)
456
457 SET_SIZE(ucopystr)
458 #endif /* lint */
|
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <sys/param.h>
27 #include <sys/errno.h>
28 #include <sys/asm_linkage.h>
29 #include <sys/vtrace.h>
30 #include <sys/machthread.h>
31 #include <sys/clock.h>
32 #include <sys/asi.h>
33 #include <sys/fsr.h>
34 #include <sys/privregs.h>
35
36 #include "assym.h"
37
38 /*
39 * Error barrier:
40 * We use membar sync to establish an error barrier for
41 * deferred errors. Membar syncs are added before any update
42 * to t_lofault to ensure that deferred errors from earlier
43 * accesses will not be reported after the membar. This error
44 * isolation is important when we try to recover from async
45 * errors which tries to distinguish kernel accesses to user
46 * data.
47 */
48
49 /*
50 * Copy a null terminated string from one point to another in
51 * the kernel address space.
52 * NOTE - don't use %o5 in this routine as copy{in,out}str uses it.
53 *
54 * copystr(from, to, maxlength, lencopied)
55 * caddr_t from, to;
56 * u_int maxlength, *lencopied;
57 */
58
59 ENTRY(copystr)
60 orcc %o2, %g0, %o4 ! save original count
61 bg,a %ncc, 1f
62 sub %o0, %o1, %o0 ! o0 gets the difference of src and dst
63
64 !
65 ! maxlength <= 0
66 !
67 bz %ncc, .cs_out ! maxlength = 0
68 mov ENAMETOOLONG, %o0
69
70 b 2f ! maxlength < 0
71 mov EFAULT, %o0 ! return failure
72
73 !
74 ! Do a byte by byte loop.
75 ! We do this instead of a word by word copy because most strings
76 ! are small and this takes a small number of cache lines.
77 !
78 0:
83
84 ba,pt %ncc, .cs_out ! last byte in string
85 mov 0, %o0 ! ret code = 0
86 1:
87 subcc %o2, 1, %o2 ! test count
88 bgeu,a %ncc, 0b
89 ldub [%o0 + %o1], %g1 ! delay slot, get source byte
90
91 mov 0, %o2 ! max number of bytes moved
92 mov ENAMETOOLONG, %o0 ! ret code = ENAMETOOLONG
93 .cs_out:
94 tst %o3
95 bz %ncc, 2f
96 sub %o4, %o2, %o4 ! compute length and store it
97 stn %o4, [%o3]
98 2:
99 retl
100 nop
101 SET_SIZE(copystr)
102
103
104 /*
105 * Copy a null terminated string from the user address space into
106 * the kernel address space.
107 */
108
109 ENTRY(copyinstr)
110 sethi %hi(.copyinstr_err), %o4
111 ldn [THREAD_REG + T_LOFAULT], %o5 ! catch faults
112 or %o4, %lo(.copyinstr_err), %o4
113 membar #Sync ! sync error barrier
114 stn %o4, [THREAD_REG + T_LOFAULT]
115
116 brz,a,pn %o2, .copyinstr_out
117 mov ENAMETOOLONG, %o0
118
119 mov %o2, %g3 ! g3 is the current count
120 mov %o1, %g4 ! g4 is the dest addr
121
122 b 1f
123 sub %o0, %o1, %g2 ! g2 gets the difference of src and dst
124
125 !
126 ! Do a byte by byte loop.
127 ! We do this instead of a word by word copy because most strings
128 ! are small and this takes a small number of cache lines.
153 stn %o5, [THREAD_REG + T_LOFAULT]
154 ldn [THREAD_REG + T_COPYOPS], %o4
155 brz %o4, 1f
156 nop
157 ldn [%o4 + CP_COPYINSTR], %g1
158 jmp %g1
159 nop
160 1:
161 retl
162 mov EFAULT, %o0
163 .copyinstr_out:
164 tst %o3 ! want length?
165 bz %ncc, 2f
166 sub %o2, %g3, %o2 ! compute length and store it
167 stn %o2, [%o3]
168 2:
169 membar #Sync ! sync error barrier
170 retl
171 stn %o5, [THREAD_REG + T_LOFAULT] ! stop catching faults
172 SET_SIZE(copyinstr)
173
174 ENTRY(copyinstr_noerr)
175 mov %o2, %o4 ! save original count
176
177 ! maxlength is unsigned so the only error is if it's 0
178 brz,a,pn %o2, .copyinstr_noerr_out
179 mov ENAMETOOLONG, %o0
180
181 b 1f
182 sub %o0, %o1, %o0 ! o0 gets the difference of src and dst
183
184 !
185 ! Do a byte by byte loop.
186 ! We do this instead of a word by word copy because most strings
187 ! are small and this takes a small number of cache lines.
188 !
189 0:
190 stb %g1, [%o1] ! store byte
191 tst %g1 ! null byte?
192 bnz 1f
193 add %o1, 1, %o1 ! incr dst addr
195 ba,pt %ncc, .copyinstr_noerr_out ! last byte in string
196 mov 0, %o0 ! ret code = 0
197 1:
198 subcc %o2, 1, %o2 ! test count
199 bgeu,a %ncc, 0b
200 lduba [%o0 + %o1]ASI_USER, %g1 ! delay slot, get source byte
201
202 mov 0, %o2 ! max number of bytes moved
203 b .copyinstr_noerr_out
204 mov ENAMETOOLONG, %o0 ! ret code = ENAMETOOLONG
205 .copyinstr_noerr_out:
206 tst %o3 ! want length?
207 bz %ncc, 2f
208 sub %o4, %o2, %o4
209 stn %o4, [%o3]
210 2:
211 retl
212 nop
213 SET_SIZE(copyinstr_noerr)
214
215 /*
216 * Copy a null terminated string from the kernel
217 * address space to the user address space.
218 */
219
220 ENTRY(copyoutstr)
221 sethi %hi(.copyoutstr_err), %o5
222 ldn [THREAD_REG + T_LOFAULT], %o4 ! catch faults
223 or %o5, %lo(.copyoutstr_err), %o5
224 membar #Sync ! sync error barrier
225 stn %o5, [THREAD_REG + T_LOFAULT]
226 mov %o4, %o5
227
228 brz,a,pn %o2, .copyoutstr_out
229 mov ENAMETOOLONG, %o0
230
231 mov %o2, %g3 ! g3 is the current count
232 mov %o1, %g4 ! g4 is the dest addr
233
234 b 1f
235 sub %o0, %o1, %g2 ! g2 gets the difference of src and dst
236
237 !
238 ! Do a byte by byte loop.
239 ! We do this instead of a word by word copy because most strings
266 ldn [THREAD_REG + T_COPYOPS], %o4
267 brz %o4, 1f
268 nop
269 ldn [%o4 + CP_COPYOUTSTR], %g1
270 jmp %g1
271 nop
272 1:
273 retl
274 mov EFAULT, %o0
275 .copyoutstr_out:
276 tst %o3 ! want length?
277 bz %ncc, 2f
278 sub %o2, %g3, %o2 ! compute length and store it
279 stn %o2, [%o3]
280 2:
281 membar #Sync ! sync error barrier
282 retl
283 stn %o5, [THREAD_REG + T_LOFAULT] ! stop catching faults
284 SET_SIZE(copyoutstr)
285
286 ENTRY(copyoutstr_noerr)
287 mov %o2, %o4 ! save original count
288
289 brz,a,pn %o2, .copyoutstr_noerr_out
290 mov ENAMETOOLONG, %o0
291
292 b 1f
293 sub %o0, %o1, %o0 ! o0 gets the difference of src and dst
294
295 !
296 ! Do a byte by byte loop.
297 ! We do this instead of a word by word copy because most strings
298 ! are small and this takes a small number of cache lines.
299 !
300 0:
301 stba %g1, [%o1]ASI_USER ! store byte
302 tst %g1 ! null byte?
303 bnz 1f
304 add %o1, 1, %o1 ! incr dst addr
305
306 b .copyoutstr_noerr_out ! last byte in string
307 mov 0, %o0 ! ret code = 0
308 1:
309 subcc %o2, 1, %o2 ! test count
310 bgeu,a %ncc, 0b
311 ldub [%o0+%o1], %g1 ! delay slot, get source byte
312
313 mov 0, %o2 ! max number of bytes moved
314 b .copyoutstr_noerr_out
315 mov ENAMETOOLONG, %o0 ! ret code = ENAMETOOLONG
316 .copyoutstr_noerr_out:
317 tst %o3 ! want length?
318 bz %ncc, 2f
319 sub %o4, %o2, %o4
320 stn %o4, [%o3]
321 2:
322 retl
323 nop
324 SET_SIZE(copyoutstr_noerr)
325
326
327 /*
328 * Copy a block of storage. If the source and target regions overlap,
329 * one or both of the regions will be silently corrupted.
330 * No fault handler installed (to be called under on_fault())
331 */
332
333 ENTRY(ucopy)
334 save %sp, -SA(MINFRAME), %sp ! get another window
335
336 subcc %g0, %i2, %i3
337 add %i0, %i2, %i0
338 bz,pn %ncc, 5f
339 add %i1, %i2, %i1
340 lduba [%i0 + %i3]ASI_USER, %i4
341 4: stba %i4, [%i1 + %i3]ASI_USER
342 inccc %i3
343 bcc,a,pt %ncc, 4b
344 lduba [%i0 + %i3]ASI_USER, %i4
345 5:
346 ret
347 restore %g0, 0, %o0 ! return (0)
348
349 SET_SIZE(ucopy)
350
351 /*
352 * Copy a user-land string. If the source and target regions overlap,
353 * one or both of the regions will be silently corrupted.
354 * No fault handler installed (to be called under on_fault())
355 */
356
357 ENTRY(ucopystr)
358 save %sp, -SA(MINFRAME), %sp ! get another window
359
360 brz %i2, 5f
361 clr %i5
362
363 lduba [%i0 + %i5]ASI_USER, %i4
364 4: stba %i4, [%i1 + %i5]ASI_USER
365 brz,pn %i4, 5f
366 inc %i5
367 deccc %i2
368 bnz,a,pt %ncc, 4b
369 lduba [%i0 + %i5]ASI_USER, %i4
370 5:
371 brnz,a,pt %i3, 6f
372 stn %i5, [%i3]
373 6:
374 ret
375 restore %g0, 0, %o0 ! return (0)
376
377 SET_SIZE(ucopystr)
|