xref: /titanic_44/usr/src/uts/sun4/ml/copy.s (revision 9acbbeaf2a1ffe5c14b244867d427714fab43c5c)
17c478bd9Sstevel@tonic-gate/*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*9acbbeafSnn35248 * Common Development and Distribution License (the "License").
6*9acbbeafSnn35248 * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate/*
22*9acbbeafSnn35248 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate#pragma ident	"%Z%%M%	%I%	%E% SMI"
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate#include <sys/param.h>
297c478bd9Sstevel@tonic-gate#include <sys/errno.h>
307c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h>
317c478bd9Sstevel@tonic-gate#include <sys/vtrace.h>
327c478bd9Sstevel@tonic-gate#include <sys/machthread.h>
337c478bd9Sstevel@tonic-gate#include <sys/clock.h>
347c478bd9Sstevel@tonic-gate#include <sys/asi.h>
357c478bd9Sstevel@tonic-gate#include <sys/fsr.h>
367c478bd9Sstevel@tonic-gate#include <sys/privregs.h>
377c478bd9Sstevel@tonic-gate
387c478bd9Sstevel@tonic-gate#if !defined(lint)
397c478bd9Sstevel@tonic-gate#include "assym.h"
407c478bd9Sstevel@tonic-gate#endif	/* lint */
417c478bd9Sstevel@tonic-gate
427c478bd9Sstevel@tonic-gate/*
437c478bd9Sstevel@tonic-gate * Error barrier:
447c478bd9Sstevel@tonic-gate * We use membar sync to establish an error barrier for
457c478bd9Sstevel@tonic-gate * deferred errors. Membar syncs are added before any update
467c478bd9Sstevel@tonic-gate * to t_lofault to ensure that deferred errors from earlier
477c478bd9Sstevel@tonic-gate * accesses will not be reported after the membar. This error
487c478bd9Sstevel@tonic-gate * isolation is important when we try to recover from async
497c478bd9Sstevel@tonic-gate * errors which tries to distinguish kernel accesses to user
507c478bd9Sstevel@tonic-gate * data.
517c478bd9Sstevel@tonic-gate */
527c478bd9Sstevel@tonic-gate
537c478bd9Sstevel@tonic-gate/*
547c478bd9Sstevel@tonic-gate * Copy a null terminated string from one point to another in
557c478bd9Sstevel@tonic-gate * the kernel address space.
567c478bd9Sstevel@tonic-gate * NOTE - don't use %o5 in this routine as copy{in,out}str uses it.
577c478bd9Sstevel@tonic-gate *
587c478bd9Sstevel@tonic-gate * copystr(from, to, maxlength, lencopied)
597c478bd9Sstevel@tonic-gate *	caddr_t from, to;
607c478bd9Sstevel@tonic-gate *	u_int maxlength, *lencopied;
617c478bd9Sstevel@tonic-gate */
627c478bd9Sstevel@tonic-gate
637c478bd9Sstevel@tonic-gate#if defined(lint)
647c478bd9Sstevel@tonic-gate
657c478bd9Sstevel@tonic-gate/* ARGSUSED */
667c478bd9Sstevel@tonic-gateint
677c478bd9Sstevel@tonic-gatecopystr(const char *from, char *to, size_t maxlength, size_t *lencopied)
687c478bd9Sstevel@tonic-gate{ return(0); }
697c478bd9Sstevel@tonic-gate
707c478bd9Sstevel@tonic-gate#else	/* lint */
717c478bd9Sstevel@tonic-gate
727c478bd9Sstevel@tonic-gate	ENTRY(copystr)
737c478bd9Sstevel@tonic-gate	orcc	%o2, %g0, %o4		! save original count
747c478bd9Sstevel@tonic-gate	bg,a	%ncc, 1f
757c478bd9Sstevel@tonic-gate	  sub	%o0, %o1, %o0		! o0 gets the difference of src and dst
767c478bd9Sstevel@tonic-gate
777c478bd9Sstevel@tonic-gate	!
787c478bd9Sstevel@tonic-gate	! maxlength <= 0
797c478bd9Sstevel@tonic-gate	!
807c478bd9Sstevel@tonic-gate	bz	%ncc, .cs_out		! maxlength = 0
817c478bd9Sstevel@tonic-gate	mov	ENAMETOOLONG, %o0
827c478bd9Sstevel@tonic-gate
837c478bd9Sstevel@tonic-gate	b	2f			! maxlength < 0
847c478bd9Sstevel@tonic-gate	mov	EFAULT, %o0		! return failure
857c478bd9Sstevel@tonic-gate
867c478bd9Sstevel@tonic-gate	!
877c478bd9Sstevel@tonic-gate	! Do a byte by byte loop.
887c478bd9Sstevel@tonic-gate	! We do this instead of a word by word copy because most strings
897c478bd9Sstevel@tonic-gate	! are small and this takes a small number of cache lines.
907c478bd9Sstevel@tonic-gate	!
917c478bd9Sstevel@tonic-gate0:
927c478bd9Sstevel@tonic-gate	stb	%g1, [%o1]		! store byte
937c478bd9Sstevel@tonic-gate	tst	%g1
947c478bd9Sstevel@tonic-gate	bnz,pt	%icc, 1f
957c478bd9Sstevel@tonic-gate	add	%o1, 1, %o1		! incr dst addr
967c478bd9Sstevel@tonic-gate
977c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .cs_out		! last byte in string
987c478bd9Sstevel@tonic-gate	mov	0, %o0			! ret code = 0
997c478bd9Sstevel@tonic-gate1:
1007c478bd9Sstevel@tonic-gate	subcc	%o2, 1, %o2		! test count
1017c478bd9Sstevel@tonic-gate	bgeu,a	%ncc, 0b
1027c478bd9Sstevel@tonic-gate	ldub	[%o0 + %o1], %g1	! delay slot, get source byte
1037c478bd9Sstevel@tonic-gate
1047c478bd9Sstevel@tonic-gate	mov	0, %o2			! max number of bytes moved
1057c478bd9Sstevel@tonic-gate	mov	ENAMETOOLONG, %o0	! ret code = ENAMETOOLONG
1067c478bd9Sstevel@tonic-gate.cs_out:
1077c478bd9Sstevel@tonic-gate	tst	%o3
1087c478bd9Sstevel@tonic-gate	bz	%ncc, 2f
1097c478bd9Sstevel@tonic-gate	sub	%o4, %o2, %o4		! compute length and store it
1107c478bd9Sstevel@tonic-gate	stn	%o4, [%o3]
1117c478bd9Sstevel@tonic-gate2:
1127c478bd9Sstevel@tonic-gate	retl
1137c478bd9Sstevel@tonic-gate	nop
1147c478bd9Sstevel@tonic-gate	SET_SIZE(copystr)
1157c478bd9Sstevel@tonic-gate
1167c478bd9Sstevel@tonic-gate#endif	/* lint */
1177c478bd9Sstevel@tonic-gate
1187c478bd9Sstevel@tonic-gate
1197c478bd9Sstevel@tonic-gate/*
1207c478bd9Sstevel@tonic-gate * Copy a null terminated string from the user address space into
1217c478bd9Sstevel@tonic-gate * the kernel address space.
1227c478bd9Sstevel@tonic-gate */
1237c478bd9Sstevel@tonic-gate#if defined(lint)
1247c478bd9Sstevel@tonic-gate
1257c478bd9Sstevel@tonic-gate/* ARGSUSED */
1267c478bd9Sstevel@tonic-gateint
1277c478bd9Sstevel@tonic-gatecopyinstr(const char *uaddr, char *kaddr, size_t maxlength,
1287c478bd9Sstevel@tonic-gate    size_t *lencopied)
1297c478bd9Sstevel@tonic-gate{ return (0); }
1307c478bd9Sstevel@tonic-gate
1317c478bd9Sstevel@tonic-gate#else	/* lint */
1327c478bd9Sstevel@tonic-gate
1337c478bd9Sstevel@tonic-gate	ENTRY(copyinstr)
1347c478bd9Sstevel@tonic-gate	sethi	%hi(.copyinstr_err), %o4
1357c478bd9Sstevel@tonic-gate	ldn	[THREAD_REG + T_LOFAULT], %o5	! catch faults
1367c478bd9Sstevel@tonic-gate	or	%o4, %lo(.copyinstr_err), %o4
1377c478bd9Sstevel@tonic-gate	membar	#Sync				! sync error barrier
1387c478bd9Sstevel@tonic-gate	stn	%o4, [THREAD_REG + T_LOFAULT]
1397c478bd9Sstevel@tonic-gate
1407c478bd9Sstevel@tonic-gate	brz,a,pn %o2, .copyinstr_out
1417c478bd9Sstevel@tonic-gate	mov	ENAMETOOLONG, %o0
1427c478bd9Sstevel@tonic-gate
1437c478bd9Sstevel@tonic-gate	mov	%o2, %g3		! g3 is the current count
1447c478bd9Sstevel@tonic-gate	mov	%o1, %g4		! g4 is the dest addr
1457c478bd9Sstevel@tonic-gate
1467c478bd9Sstevel@tonic-gate	b	1f
1477c478bd9Sstevel@tonic-gate	sub	%o0, %o1, %g2		! g2 gets the difference of src and dst
1487c478bd9Sstevel@tonic-gate
1497c478bd9Sstevel@tonic-gate	!
1507c478bd9Sstevel@tonic-gate	! Do a byte by byte loop.
1517c478bd9Sstevel@tonic-gate	! We do this instead of a word by word copy because most strings
1527c478bd9Sstevel@tonic-gate	! are small and this takes a small number of cache lines.
1537c478bd9Sstevel@tonic-gate	!
1547c478bd9Sstevel@tonic-gate0:
1557c478bd9Sstevel@tonic-gate	stb	%g1, [%g4]		! store byte
1567c478bd9Sstevel@tonic-gate	tst	%g1
1577c478bd9Sstevel@tonic-gate	bnz,pt	%icc, 1f
1587c478bd9Sstevel@tonic-gate	add	%g4, 1, %g4		! incr dst addr
1597c478bd9Sstevel@tonic-gate
1607c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .copyinstr_out	! last byte in string
1617c478bd9Sstevel@tonic-gate	mov	0, %o0			! ret code = 0
1627c478bd9Sstevel@tonic-gate1:
1637c478bd9Sstevel@tonic-gate	subcc	%g3, 1, %g3		! test count
1647c478bd9Sstevel@tonic-gate	bgeu,a	%ncc, 0b
1657c478bd9Sstevel@tonic-gate	lduba	[%g2+%g4]ASI_USER, %g1	! delay slot, get source byte
1667c478bd9Sstevel@tonic-gate
1677c478bd9Sstevel@tonic-gate	mov	0, %g3			! max number of bytes moved
1687c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .copyinstr_out
1697c478bd9Sstevel@tonic-gate	  mov	ENAMETOOLONG, %o0	! ret code = ENAMETOOLONG
1707c478bd9Sstevel@tonic-gate
1717c478bd9Sstevel@tonic-gate/*
1727c478bd9Sstevel@tonic-gate * Fault while trying to move from or to user space.
1737c478bd9Sstevel@tonic-gate * Set and return error code.
1747c478bd9Sstevel@tonic-gate */
1757c478bd9Sstevel@tonic-gate.copyinstr_err:
1767c478bd9Sstevel@tonic-gate	membar	#Sync			! sync error barrier
1777c478bd9Sstevel@tonic-gate	stn	%o5, [THREAD_REG + T_LOFAULT]
1787c478bd9Sstevel@tonic-gate	ldn	[THREAD_REG + T_COPYOPS], %o4
1797c478bd9Sstevel@tonic-gate	brz	%o4, 1f
1807c478bd9Sstevel@tonic-gate	nop
1817c478bd9Sstevel@tonic-gate	ldn	[%o4 + CP_COPYINSTR], %g1
1827c478bd9Sstevel@tonic-gate	jmp	%g1
1837c478bd9Sstevel@tonic-gate	nop
1847c478bd9Sstevel@tonic-gate1:
1857c478bd9Sstevel@tonic-gate	retl
1867c478bd9Sstevel@tonic-gate	mov	EFAULT, %o0
1877c478bd9Sstevel@tonic-gate.copyinstr_out:
1887c478bd9Sstevel@tonic-gate	tst	%o3			! want length?
1897c478bd9Sstevel@tonic-gate	bz	%ncc, 2f
1907c478bd9Sstevel@tonic-gate	sub	%o2, %g3, %o2		! compute length and store it
1917c478bd9Sstevel@tonic-gate	stn	%o2, [%o3]
1927c478bd9Sstevel@tonic-gate2:
1937c478bd9Sstevel@tonic-gate	membar	#Sync			! sync error barrier
1947c478bd9Sstevel@tonic-gate	retl
1957c478bd9Sstevel@tonic-gate	stn	%o5, [THREAD_REG + T_LOFAULT]	! stop catching faults
1967c478bd9Sstevel@tonic-gate	SET_SIZE(copyinstr)
1977c478bd9Sstevel@tonic-gate#endif
1987c478bd9Sstevel@tonic-gate
1997c478bd9Sstevel@tonic-gate#if defined(lint)
2007c478bd9Sstevel@tonic-gate
2017c478bd9Sstevel@tonic-gate/* ARGSUSED */
2027c478bd9Sstevel@tonic-gateint
2037c478bd9Sstevel@tonic-gatecopyinstr_noerr(const char *uaddr, char *kaddr, size_t maxlength,
2047c478bd9Sstevel@tonic-gate    size_t *lencopied)
2057c478bd9Sstevel@tonic-gate{ return (0); }
2067c478bd9Sstevel@tonic-gate
2077c478bd9Sstevel@tonic-gate#else	/* lint */
2087c478bd9Sstevel@tonic-gate
2097c478bd9Sstevel@tonic-gate	ENTRY(copyinstr_noerr)
2107c478bd9Sstevel@tonic-gate	mov	%o2, %o4		! save original count
2117c478bd9Sstevel@tonic-gate
2127c478bd9Sstevel@tonic-gate	! maxlength is unsigned so the only error is if it's 0
2137c478bd9Sstevel@tonic-gate	brz,a,pn %o2, .copyinstr_noerr_out
2147c478bd9Sstevel@tonic-gate	mov	ENAMETOOLONG, %o0
2157c478bd9Sstevel@tonic-gate
2167c478bd9Sstevel@tonic-gate	b	1f
2177c478bd9Sstevel@tonic-gate	sub	%o0, %o1, %o0		! o0 gets the difference of src and dst
2187c478bd9Sstevel@tonic-gate
2197c478bd9Sstevel@tonic-gate	!
2207c478bd9Sstevel@tonic-gate	! Do a byte by byte loop.
2217c478bd9Sstevel@tonic-gate	! We do this instead of a word by word copy because most strings
2227c478bd9Sstevel@tonic-gate	! are small and this takes a small number of cache lines.
2237c478bd9Sstevel@tonic-gate	!
2247c478bd9Sstevel@tonic-gate0:
2257c478bd9Sstevel@tonic-gate	stb	%g1, [%o1]		! store byte
2267c478bd9Sstevel@tonic-gate	tst	%g1			! null byte?
2277c478bd9Sstevel@tonic-gate	bnz	1f
2287c478bd9Sstevel@tonic-gate	add	%o1, 1, %o1		! incr dst addr
2297c478bd9Sstevel@tonic-gate
2307c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .copyinstr_noerr_out	! last byte in string
2317c478bd9Sstevel@tonic-gate	mov	0, %o0			! ret code = 0
2327c478bd9Sstevel@tonic-gate1:
2337c478bd9Sstevel@tonic-gate	subcc	%o2, 1, %o2		! test count
2347c478bd9Sstevel@tonic-gate	bgeu,a	%ncc, 0b
2357c478bd9Sstevel@tonic-gate	lduba	[%o0 + %o1]ASI_USER, %g1	! delay slot, get source byte
2367c478bd9Sstevel@tonic-gate
2377c478bd9Sstevel@tonic-gate	mov	0, %o2			! max number of bytes moved
2387c478bd9Sstevel@tonic-gate	b	.copyinstr_noerr_out
2397c478bd9Sstevel@tonic-gate	  mov	ENAMETOOLONG, %o0	! ret code = ENAMETOOLONG
2407c478bd9Sstevel@tonic-gate.copyinstr_noerr_out:
2417c478bd9Sstevel@tonic-gate	tst	%o3			! want length?
2427c478bd9Sstevel@tonic-gate	bz	%ncc, 2f
2437c478bd9Sstevel@tonic-gate	sub	%o4, %o2, %o4
2447c478bd9Sstevel@tonic-gate	stn	%o4, [%o3]
2457c478bd9Sstevel@tonic-gate2:
2467c478bd9Sstevel@tonic-gate	retl
2477c478bd9Sstevel@tonic-gate	nop
2487c478bd9Sstevel@tonic-gate	SET_SIZE(copyinstr_noerr)
2497c478bd9Sstevel@tonic-gate
2507c478bd9Sstevel@tonic-gate#endif	/* lint */
2517c478bd9Sstevel@tonic-gate
2527c478bd9Sstevel@tonic-gate/*
2537c478bd9Sstevel@tonic-gate * Copy a null terminated string from the kernel
2547c478bd9Sstevel@tonic-gate * address space to the user address space.
2557c478bd9Sstevel@tonic-gate */
2567c478bd9Sstevel@tonic-gate
2577c478bd9Sstevel@tonic-gate#if defined(lint)
2587c478bd9Sstevel@tonic-gate
2597c478bd9Sstevel@tonic-gate/* ARGSUSED */
2607c478bd9Sstevel@tonic-gateint
2617c478bd9Sstevel@tonic-gatecopyoutstr(const char *kaddr, char *uaddr, size_t maxlength,
2627c478bd9Sstevel@tonic-gate    size_t *lencopied)
2637c478bd9Sstevel@tonic-gate{ return (0); }
2647c478bd9Sstevel@tonic-gate
2657c478bd9Sstevel@tonic-gate#else	/* lint */
2667c478bd9Sstevel@tonic-gate
2677c478bd9Sstevel@tonic-gate	ENTRY(copyoutstr)
2687c478bd9Sstevel@tonic-gate	sethi	%hi(.copyoutstr_err), %o5
2697c478bd9Sstevel@tonic-gate	ldn	[THREAD_REG + T_LOFAULT], %o4	! catch faults
2707c478bd9Sstevel@tonic-gate	or	%o5, %lo(.copyoutstr_err), %o5
2717c478bd9Sstevel@tonic-gate	membar	#Sync				! sync error barrier
2727c478bd9Sstevel@tonic-gate	stn	%o5, [THREAD_REG + T_LOFAULT]
2737c478bd9Sstevel@tonic-gate	mov	%o4, %o5
2747c478bd9Sstevel@tonic-gate
2757c478bd9Sstevel@tonic-gate	brz,a,pn %o2, .copyoutstr_out
2767c478bd9Sstevel@tonic-gate	mov	ENAMETOOLONG, %o0
2777c478bd9Sstevel@tonic-gate
2787c478bd9Sstevel@tonic-gate	mov	%o2, %g3		! g3 is the current count
2797c478bd9Sstevel@tonic-gate	mov	%o1, %g4		! g4 is the dest addr
2807c478bd9Sstevel@tonic-gate
2817c478bd9Sstevel@tonic-gate	b	1f
2827c478bd9Sstevel@tonic-gate	sub	%o0, %o1, %g2		! g2 gets the difference of src and dst
2837c478bd9Sstevel@tonic-gate
2847c478bd9Sstevel@tonic-gate	!
2857c478bd9Sstevel@tonic-gate	! Do a byte by byte loop.
2867c478bd9Sstevel@tonic-gate	! We do this instead of a word by word copy because most strings
2877c478bd9Sstevel@tonic-gate	! are small and this takes a small number of cache lines.
2887c478bd9Sstevel@tonic-gate	!
2897c478bd9Sstevel@tonic-gate0:
2907c478bd9Sstevel@tonic-gate	stba	%g1, [%g4]ASI_USER	! store byte
2917c478bd9Sstevel@tonic-gate	tst	%g1
2927c478bd9Sstevel@tonic-gate	bnz,pt	%icc, 1f
2937c478bd9Sstevel@tonic-gate	add	%g4, 1, %g4		! incr dst addr
2947c478bd9Sstevel@tonic-gate
2957c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .copyoutstr_out	! last byte in string
2967c478bd9Sstevel@tonic-gate	mov	0, %o0			! ret code = 0
2977c478bd9Sstevel@tonic-gate1:
2987c478bd9Sstevel@tonic-gate	subcc	%g3, 1, %g3		! test count
2997c478bd9Sstevel@tonic-gate	bgeu,a	%ncc, 0b
3007c478bd9Sstevel@tonic-gate	ldub	[%g2 + %g4], %g1	! delay slot, get source byte
3017c478bd9Sstevel@tonic-gate
3027c478bd9Sstevel@tonic-gate	mov	0, %g3			! max number of bytes moved
3037c478bd9Sstevel@tonic-gate	ba,pt	%ncc, .copyoutstr_out
3047c478bd9Sstevel@tonic-gate	  mov	ENAMETOOLONG, %o0	! ret code = ENAMETOOLONG
3057c478bd9Sstevel@tonic-gate
3067c478bd9Sstevel@tonic-gate/*
3077c478bd9Sstevel@tonic-gate * Fault while trying to move from or to user space.
3087c478bd9Sstevel@tonic-gate * Set and return error code.
3097c478bd9Sstevel@tonic-gate */
3107c478bd9Sstevel@tonic-gate.copyoutstr_err:
3117c478bd9Sstevel@tonic-gate	membar	#Sync			! sync error barrier
3127c478bd9Sstevel@tonic-gate	stn	%o5, [THREAD_REG + T_LOFAULT]
3137c478bd9Sstevel@tonic-gate	ldn	[THREAD_REG + T_COPYOPS], %o4
3147c478bd9Sstevel@tonic-gate	brz	%o4, 1f
3157c478bd9Sstevel@tonic-gate	nop
3167c478bd9Sstevel@tonic-gate	ldn	[%o4 + CP_COPYOUTSTR], %g1
3177c478bd9Sstevel@tonic-gate	jmp	%g1
3187c478bd9Sstevel@tonic-gate	nop
3197c478bd9Sstevel@tonic-gate1:
3207c478bd9Sstevel@tonic-gate	retl
3217c478bd9Sstevel@tonic-gate	mov	EFAULT, %o0
3227c478bd9Sstevel@tonic-gate.copyoutstr_out:
3237c478bd9Sstevel@tonic-gate	tst	%o3			! want length?
3247c478bd9Sstevel@tonic-gate	bz	%ncc, 2f
3257c478bd9Sstevel@tonic-gate	sub	%o2, %g3, %o2		! compute length and store it
3267c478bd9Sstevel@tonic-gate	stn	%o2, [%o3]
3277c478bd9Sstevel@tonic-gate2:
3287c478bd9Sstevel@tonic-gate	membar	#Sync			! sync error barrier
3297c478bd9Sstevel@tonic-gate	retl
3307c478bd9Sstevel@tonic-gate	stn	%o5, [THREAD_REG + T_LOFAULT]	! stop catching faults
3317c478bd9Sstevel@tonic-gate	SET_SIZE(copyoutstr)
3327c478bd9Sstevel@tonic-gate
3337c478bd9Sstevel@tonic-gate#endif	/* lint */
3347c478bd9Sstevel@tonic-gate
3357c478bd9Sstevel@tonic-gate#if defined(lint)
3367c478bd9Sstevel@tonic-gate
3377c478bd9Sstevel@tonic-gate/* ARGSUSED */
3387c478bd9Sstevel@tonic-gateint
3397c478bd9Sstevel@tonic-gatecopyoutstr_noerr(const char *kaddr, char *uaddr, size_t maxlength,
3407c478bd9Sstevel@tonic-gate    size_t *lencopied)
3417c478bd9Sstevel@tonic-gate{ return (0); }
3427c478bd9Sstevel@tonic-gate
3437c478bd9Sstevel@tonic-gate#else	/* lint */
3447c478bd9Sstevel@tonic-gate
3457c478bd9Sstevel@tonic-gate	ENTRY(copyoutstr_noerr)
3467c478bd9Sstevel@tonic-gate	mov	%o2, %o4		! save original count
3477c478bd9Sstevel@tonic-gate
3487c478bd9Sstevel@tonic-gate	brz,a,pn %o2, .copyoutstr_noerr_out
3497c478bd9Sstevel@tonic-gate	mov	ENAMETOOLONG, %o0
3507c478bd9Sstevel@tonic-gate
3517c478bd9Sstevel@tonic-gate	b	1f
3527c478bd9Sstevel@tonic-gate	sub	%o0, %o1, %o0		! o0 gets the difference of src and dst
3537c478bd9Sstevel@tonic-gate
3547c478bd9Sstevel@tonic-gate	!
3557c478bd9Sstevel@tonic-gate	! Do a byte by byte loop.
3567c478bd9Sstevel@tonic-gate	! We do this instead of a word by word copy because most strings
3577c478bd9Sstevel@tonic-gate	! are small and this takes a small number of cache lines.
3587c478bd9Sstevel@tonic-gate	!
3597c478bd9Sstevel@tonic-gate0:
3607c478bd9Sstevel@tonic-gate	stba	%g1, [%o1]ASI_USER	! store byte
3617c478bd9Sstevel@tonic-gate	tst	%g1			! null byte?
3627c478bd9Sstevel@tonic-gate	bnz	1f
3637c478bd9Sstevel@tonic-gate	add	%o1, 1, %o1		! incr dst addr
3647c478bd9Sstevel@tonic-gate
3657c478bd9Sstevel@tonic-gate	b	.copyoutstr_noerr_out	! last byte in string
3667c478bd9Sstevel@tonic-gate	mov	0, %o0			! ret code = 0
3677c478bd9Sstevel@tonic-gate1:
3687c478bd9Sstevel@tonic-gate	subcc	%o2, 1, %o2		! test count
3697c478bd9Sstevel@tonic-gate	bgeu,a	%ncc, 0b
3707c478bd9Sstevel@tonic-gate	ldub	[%o0+%o1], %g1	! delay slot, get source byte
3717c478bd9Sstevel@tonic-gate
3727c478bd9Sstevel@tonic-gate	mov	0, %o2			! max number of bytes moved
3737c478bd9Sstevel@tonic-gate	b	.copyoutstr_noerr_out
3747c478bd9Sstevel@tonic-gate	  mov	ENAMETOOLONG, %o0	! ret code = ENAMETOOLONG
3757c478bd9Sstevel@tonic-gate.copyoutstr_noerr_out:
3767c478bd9Sstevel@tonic-gate	tst	%o3			! want length?
3777c478bd9Sstevel@tonic-gate	bz	%ncc, 2f
3787c478bd9Sstevel@tonic-gate	sub	%o4, %o2, %o4
3797c478bd9Sstevel@tonic-gate	stn	%o4, [%o3]
3807c478bd9Sstevel@tonic-gate2:
3817c478bd9Sstevel@tonic-gate	retl
3827c478bd9Sstevel@tonic-gate	nop
3837c478bd9Sstevel@tonic-gate	SET_SIZE(copyoutstr_noerr)
3847c478bd9Sstevel@tonic-gate
3857c478bd9Sstevel@tonic-gate#endif	/* lint */
3867c478bd9Sstevel@tonic-gate
3877c478bd9Sstevel@tonic-gate
3887c478bd9Sstevel@tonic-gate/*
389*9acbbeafSnn35248 * Copy a block of storage.  If the source and target regions overlap,
390*9acbbeafSnn35248 * one or both of the regions will be silently corrupted.
3917c478bd9Sstevel@tonic-gate * No fault handler installed (to be called under on_fault())
3927c478bd9Sstevel@tonic-gate */
3937c478bd9Sstevel@tonic-gate
3947c478bd9Sstevel@tonic-gate#if defined(lint)
3957c478bd9Sstevel@tonic-gate
3967c478bd9Sstevel@tonic-gate/* ARGSUSED */
3977c478bd9Sstevel@tonic-gatevoid
3987c478bd9Sstevel@tonic-gateucopy(const void *ufrom, void *uto, size_t ulength)
3997c478bd9Sstevel@tonic-gate{}
4007c478bd9Sstevel@tonic-gate
4017c478bd9Sstevel@tonic-gate#else /* lint */
4027c478bd9Sstevel@tonic-gate
4037c478bd9Sstevel@tonic-gate	ENTRY(ucopy)
4047c478bd9Sstevel@tonic-gate	save	%sp, -SA(MINFRAME), %sp ! get another window
4057c478bd9Sstevel@tonic-gate
4067c478bd9Sstevel@tonic-gate	subcc	%g0, %i2, %i3
4077c478bd9Sstevel@tonic-gate	add	%i0, %i2, %i0
4087c478bd9Sstevel@tonic-gate	bz,pn	%ncc, 5f
4097c478bd9Sstevel@tonic-gate	add	%i1, %i2, %i1
4107c478bd9Sstevel@tonic-gate	lduba	[%i0 + %i3]ASI_USER, %i4
4117c478bd9Sstevel@tonic-gate4:	stba	%i4, [%i1 + %i3]ASI_USER
4127c478bd9Sstevel@tonic-gate	inccc	%i3
4137c478bd9Sstevel@tonic-gate	bcc,a,pt %ncc, 4b
4147c478bd9Sstevel@tonic-gate	lduba  [%i0 + %i3]ASI_USER, %i4
4157c478bd9Sstevel@tonic-gate5:
4167c478bd9Sstevel@tonic-gate	ret
4177c478bd9Sstevel@tonic-gate	restore %g0, 0, %o0		! return (0)
4187c478bd9Sstevel@tonic-gate
4197c478bd9Sstevel@tonic-gate	SET_SIZE(ucopy)
4207c478bd9Sstevel@tonic-gate#endif /* lint */
421*9acbbeafSnn35248
422*9acbbeafSnn35248/*
423*9acbbeafSnn35248 * Copy a user-land string.  If the source and target regions overlap,
424*9acbbeafSnn35248 * one or both of the regions will be silently corrupted.
425*9acbbeafSnn35248 * No fault handler installed (to be called under on_fault())
426*9acbbeafSnn35248 */
427*9acbbeafSnn35248
428*9acbbeafSnn35248#if defined(lint)
429*9acbbeafSnn35248
430*9acbbeafSnn35248/* ARGSUSED */
431*9acbbeafSnn35248void
432*9acbbeafSnn35248ucopystr(const char *ufrom, char *uto, size_t umaxlength, size_t *ulencopied)
433*9acbbeafSnn35248{}
434*9acbbeafSnn35248
435*9acbbeafSnn35248#else /* lint */
436*9acbbeafSnn35248
437*9acbbeafSnn35248	ENTRY(ucopystr)
438*9acbbeafSnn35248	save	%sp, -SA(MINFRAME), %sp ! get another window
439*9acbbeafSnn35248
440*9acbbeafSnn35248	brz	%i2, 5f
441*9acbbeafSnn35248	clr	%i5
442*9acbbeafSnn35248
443*9acbbeafSnn35248	lduba	[%i0 + %i5]ASI_USER, %i4
444*9acbbeafSnn352484:	stba	%i4, [%i1 + %i5]ASI_USER
445*9acbbeafSnn35248	brz,pn	%i4, 5f
446*9acbbeafSnn35248	inc	%i5
447*9acbbeafSnn35248	deccc	%i2
448*9acbbeafSnn35248	bnz,a,pt %ncc, 4b
449*9acbbeafSnn35248	lduba	[%i0 + %i5]ASI_USER, %i4
450*9acbbeafSnn352485:
451*9acbbeafSnn35248	brnz,a,pt %i3, 6f
452*9acbbeafSnn35248	stn	%i5, [%i3]
453*9acbbeafSnn352486:
454*9acbbeafSnn35248	ret
455*9acbbeafSnn35248	restore %g0, 0, %o0		! return (0)
456*9acbbeafSnn35248
457*9acbbeafSnn35248	SET_SIZE(ucopystr)
458*9acbbeafSnn35248#endif /* lint */
459