xref: /titanic_44/usr/src/uts/intel/ia32/ml/copy.s (revision 9b6707c598bbcc5351bcf053830ed06dad19fc83)
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
59acbbeafSnn35248 * Common Development and Distribution License (the "License").
69acbbeafSnn35248 * 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/*
22b08adf18SBill Holler * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
2622cc0e45SBill Holler/*
27b08adf18SBill Holler * Copyright (c) 2009, Intel Corporation
2822cc0e45SBill Holler * All rights reserved.
2922cc0e45SBill Holler */
3022cc0e45SBill Holler
317c478bd9Sstevel@tonic-gate/*       Copyright (c) 1990, 1991 UNIX System Laboratories, Inc.	*/
327c478bd9Sstevel@tonic-gate/*       Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T		*/
337c478bd9Sstevel@tonic-gate/*         All Rights Reserved						*/
347c478bd9Sstevel@tonic-gate
357c478bd9Sstevel@tonic-gate/*       Copyright (c) 1987, 1988 Microsoft Corporation			*/
367c478bd9Sstevel@tonic-gate/*         All Rights Reserved						*/
377c478bd9Sstevel@tonic-gate
38*9b6707c5SRobert Mustacchi/*
39*9b6707c5SRobert Mustacchi * Copyright 2016 Joyent, Inc.
40*9b6707c5SRobert Mustacchi */
41*9b6707c5SRobert Mustacchi
427c478bd9Sstevel@tonic-gate#include <sys/errno.h>
437c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h>
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate#if defined(__lint)
467c478bd9Sstevel@tonic-gate#include <sys/types.h>
477c478bd9Sstevel@tonic-gate#include <sys/systm.h>
487c478bd9Sstevel@tonic-gate#else	/* __lint */
497c478bd9Sstevel@tonic-gate#include "assym.h"
507c478bd9Sstevel@tonic-gate#endif	/* __lint */
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate#define	KCOPY_MIN_SIZE	128	/* Must be >= 16 bytes */
537c478bd9Sstevel@tonic-gate#define	XCOPY_MIN_SIZE	128	/* Must be >= 16 bytes */
547c478bd9Sstevel@tonic-gate/*
557c478bd9Sstevel@tonic-gate * Non-temopral access (NTA) alignment requirement
567c478bd9Sstevel@tonic-gate */
577c478bd9Sstevel@tonic-gate#define	NTA_ALIGN_SIZE	4	/* Must be at least 4-byte aligned */
587c478bd9Sstevel@tonic-gate#define	NTA_ALIGN_MASK	_CONST(NTA_ALIGN_SIZE-1)
597c478bd9Sstevel@tonic-gate#define	COUNT_ALIGN_SIZE	16	/* Must be at least 16-byte aligned */
607c478bd9Sstevel@tonic-gate#define	COUNT_ALIGN_MASK	_CONST(COUNT_ALIGN_SIZE-1)
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate/*
6322cc0e45SBill Holler * The optimal 64-bit bcopy and kcopy for modern x86 processors uses
6422cc0e45SBill Holler * "rep smovq" for large sizes. Performance data shows that many calls to
6522cc0e45SBill Holler * bcopy/kcopy/bzero/kzero operate on small buffers. For best performance for
6622cc0e45SBill Holler * these small sizes unrolled code is used. For medium sizes loops writing
6722cc0e45SBill Holler * 64-bytes per loop are used. Transition points were determined experimentally.
6822cc0e45SBill Holler */
6922cc0e45SBill Holler#define BZERO_USE_REP	(1024)
7022cc0e45SBill Holler#define BCOPY_DFLT_REP	(128)
7122cc0e45SBill Holler#define	BCOPY_NHM_REP	(768)
7222cc0e45SBill Holler
7322cc0e45SBill Holler/*
747c478bd9Sstevel@tonic-gate * Copy a block of storage, returning an error code if `from' or
757c478bd9Sstevel@tonic-gate * `to' takes a kernel pagefault which cannot be resolved.
767c478bd9Sstevel@tonic-gate * Returns errno value on pagefault error, 0 if all ok
777c478bd9Sstevel@tonic-gate */
787c478bd9Sstevel@tonic-gate
797c478bd9Sstevel@tonic-gate#if defined(__lint)
807c478bd9Sstevel@tonic-gate
817c478bd9Sstevel@tonic-gate/* ARGSUSED */
827c478bd9Sstevel@tonic-gateint
837c478bd9Sstevel@tonic-gatekcopy(const void *from, void *to, size_t count)
847c478bd9Sstevel@tonic-gate{ return (0); }
857c478bd9Sstevel@tonic-gate
867c478bd9Sstevel@tonic-gate#else	/* __lint */
877c478bd9Sstevel@tonic-gate
887c478bd9Sstevel@tonic-gate	.globl	kernelbase
89ae115bc7Smrj	.globl	postbootkernelbase
907c478bd9Sstevel@tonic-gate
917c478bd9Sstevel@tonic-gate#if defined(__amd64)
927c478bd9Sstevel@tonic-gate
937c478bd9Sstevel@tonic-gate	ENTRY(kcopy)
947c478bd9Sstevel@tonic-gate	pushq	%rbp
957c478bd9Sstevel@tonic-gate	movq	%rsp, %rbp
967c478bd9Sstevel@tonic-gate#ifdef DEBUG
97ae115bc7Smrj	cmpq	postbootkernelbase(%rip), %rdi 		/* %rdi = from */
987c478bd9Sstevel@tonic-gate	jb	0f
99ae115bc7Smrj	cmpq	postbootkernelbase(%rip), %rsi		/* %rsi = to */
1007c478bd9Sstevel@tonic-gate	jnb	1f
1017c478bd9Sstevel@tonic-gate0:	leaq	.kcopy_panic_msg(%rip), %rdi
1027c478bd9Sstevel@tonic-gate	xorl	%eax, %eax
1037c478bd9Sstevel@tonic-gate	call	panic
1047c478bd9Sstevel@tonic-gate1:
1057c478bd9Sstevel@tonic-gate#endif
1067c478bd9Sstevel@tonic-gate	/*
1077c478bd9Sstevel@tonic-gate	 * pass lofault value as 4th argument to do_copy_fault
1087c478bd9Sstevel@tonic-gate	 */
1097c478bd9Sstevel@tonic-gate	leaq	_kcopy_copyerr(%rip), %rcx
1107c478bd9Sstevel@tonic-gate	movq	%gs:CPU_THREAD, %r9	/* %r9 = thread addr */
1117c478bd9Sstevel@tonic-gate
1127c478bd9Sstevel@tonic-gatedo_copy_fault:
1137c478bd9Sstevel@tonic-gate	movq	T_LOFAULT(%r9), %r11	/* save the current lofault */
1147c478bd9Sstevel@tonic-gate	movq	%rcx, T_LOFAULT(%r9)	/* new lofault */
11522cc0e45SBill Holler	call	bcopy_altentry
1167c478bd9Sstevel@tonic-gate	xorl	%eax, %eax		/* return 0 (success) */
1177c478bd9Sstevel@tonic-gate
1187c478bd9Sstevel@tonic-gate	/*
1197c478bd9Sstevel@tonic-gate	 * A fault during do_copy_fault is indicated through an errno value
1207c478bd9Sstevel@tonic-gate	 * in %rax and we iretq from the trap handler to here.
1217c478bd9Sstevel@tonic-gate	 */
1227c478bd9Sstevel@tonic-gate_kcopy_copyerr:
1237c478bd9Sstevel@tonic-gate	movq	%r11, T_LOFAULT(%r9)	/* restore original lofault */
1247c478bd9Sstevel@tonic-gate	leave
1257c478bd9Sstevel@tonic-gate	ret
1267c478bd9Sstevel@tonic-gate	SET_SIZE(kcopy)
1277c478bd9Sstevel@tonic-gate
1287c478bd9Sstevel@tonic-gate#elif defined(__i386)
1297c478bd9Sstevel@tonic-gate
1307c478bd9Sstevel@tonic-gate#define	ARG_FROM	8
1317c478bd9Sstevel@tonic-gate#define	ARG_TO		12
1327c478bd9Sstevel@tonic-gate#define	ARG_COUNT	16
1337c478bd9Sstevel@tonic-gate
1347c478bd9Sstevel@tonic-gate	ENTRY(kcopy)
1357c478bd9Sstevel@tonic-gate#ifdef DEBUG
1367c478bd9Sstevel@tonic-gate	pushl	%ebp
1377c478bd9Sstevel@tonic-gate	movl	%esp, %ebp
138ae115bc7Smrj	movl	postbootkernelbase, %eax
1397c478bd9Sstevel@tonic-gate	cmpl	%eax, ARG_FROM(%ebp)
1407c478bd9Sstevel@tonic-gate	jb	0f
1417c478bd9Sstevel@tonic-gate	cmpl	%eax, ARG_TO(%ebp)
1427c478bd9Sstevel@tonic-gate	jnb	1f
1437c478bd9Sstevel@tonic-gate0:	pushl	$.kcopy_panic_msg
1447c478bd9Sstevel@tonic-gate	call	panic
1457c478bd9Sstevel@tonic-gate1:	popl	%ebp
1467c478bd9Sstevel@tonic-gate#endif
1477c478bd9Sstevel@tonic-gate	lea	_kcopy_copyerr, %eax	/* lofault value */
1487c478bd9Sstevel@tonic-gate	movl	%gs:CPU_THREAD, %edx
1497c478bd9Sstevel@tonic-gate
1507c478bd9Sstevel@tonic-gatedo_copy_fault:
1517c478bd9Sstevel@tonic-gate	pushl	%ebp
1527c478bd9Sstevel@tonic-gate	movl	%esp, %ebp		/* setup stack frame */
1537c478bd9Sstevel@tonic-gate	pushl	%esi
1547c478bd9Sstevel@tonic-gate	pushl	%edi			/* save registers */
1557c478bd9Sstevel@tonic-gate
1567c478bd9Sstevel@tonic-gate	movl	T_LOFAULT(%edx), %edi
1577c478bd9Sstevel@tonic-gate	pushl	%edi			/* save the current lofault */
1587c478bd9Sstevel@tonic-gate	movl	%eax, T_LOFAULT(%edx)	/* new lofault */
1597c478bd9Sstevel@tonic-gate
1607c478bd9Sstevel@tonic-gate	movl	ARG_COUNT(%ebp), %ecx
1617c478bd9Sstevel@tonic-gate	movl	ARG_FROM(%ebp), %esi
1627c478bd9Sstevel@tonic-gate	movl	ARG_TO(%ebp), %edi
1637c478bd9Sstevel@tonic-gate	shrl	$2, %ecx		/* word count */
1647c478bd9Sstevel@tonic-gate	rep
1657c478bd9Sstevel@tonic-gate	  smovl
1667c478bd9Sstevel@tonic-gate	movl	ARG_COUNT(%ebp), %ecx
1677c478bd9Sstevel@tonic-gate	andl	$3, %ecx		/* bytes left over */
1687c478bd9Sstevel@tonic-gate	rep
1697c478bd9Sstevel@tonic-gate	  smovb
1707c478bd9Sstevel@tonic-gate	xorl	%eax, %eax
1717c478bd9Sstevel@tonic-gate
1727c478bd9Sstevel@tonic-gate	/*
1737c478bd9Sstevel@tonic-gate	 * A fault during do_copy_fault is indicated through an errno value
1747c478bd9Sstevel@tonic-gate	 * in %eax and we iret from the trap handler to here.
1757c478bd9Sstevel@tonic-gate	 */
1767c478bd9Sstevel@tonic-gate_kcopy_copyerr:
1777c478bd9Sstevel@tonic-gate	popl	%ecx
1787c478bd9Sstevel@tonic-gate	popl	%edi
1797c478bd9Sstevel@tonic-gate	movl	%ecx, T_LOFAULT(%edx)	/* restore the original lofault */
1807c478bd9Sstevel@tonic-gate	popl	%esi
1817c478bd9Sstevel@tonic-gate	popl	%ebp
1827c478bd9Sstevel@tonic-gate	ret
1837c478bd9Sstevel@tonic-gate	SET_SIZE(kcopy)
1847c478bd9Sstevel@tonic-gate
1857c478bd9Sstevel@tonic-gate#undef	ARG_FROM
1867c478bd9Sstevel@tonic-gate#undef	ARG_TO
1877c478bd9Sstevel@tonic-gate#undef	ARG_COUNT
1887c478bd9Sstevel@tonic-gate
1897c478bd9Sstevel@tonic-gate#endif	/* __i386 */
1907c478bd9Sstevel@tonic-gate#endif	/* __lint */
1917c478bd9Sstevel@tonic-gate
1927c478bd9Sstevel@tonic-gate#if defined(__lint)
1937c478bd9Sstevel@tonic-gate
1947c478bd9Sstevel@tonic-gate/*
1957c478bd9Sstevel@tonic-gate * Copy a block of storage.  Similar to kcopy but uses non-temporal
1967c478bd9Sstevel@tonic-gate * instructions.
1977c478bd9Sstevel@tonic-gate */
1987c478bd9Sstevel@tonic-gate
1997c478bd9Sstevel@tonic-gate/* ARGSUSED */
2007c478bd9Sstevel@tonic-gateint
2017c478bd9Sstevel@tonic-gatekcopy_nta(const void *from, void *to, size_t count, int copy_cached)
2027c478bd9Sstevel@tonic-gate{ return (0); }
2037c478bd9Sstevel@tonic-gate
2047c478bd9Sstevel@tonic-gate#else	/* __lint */
2057c478bd9Sstevel@tonic-gate
2067c478bd9Sstevel@tonic-gate#if defined(__amd64)
2077c478bd9Sstevel@tonic-gate
2087c478bd9Sstevel@tonic-gate#define	COPY_LOOP_INIT(src, dst, cnt)	\
2097c478bd9Sstevel@tonic-gate	addq	cnt, src;			\
2107c478bd9Sstevel@tonic-gate	addq	cnt, dst;			\
2117c478bd9Sstevel@tonic-gate	shrq	$3, cnt;			\
2127c478bd9Sstevel@tonic-gate	neg	cnt
2137c478bd9Sstevel@tonic-gate
2147c478bd9Sstevel@tonic-gate	/* Copy 16 bytes per loop.  Uses %rax and %r8 */
2157c478bd9Sstevel@tonic-gate#define	COPY_LOOP_BODY(src, dst, cnt)	\
2167c478bd9Sstevel@tonic-gate	prefetchnta	0x100(src, cnt, 8);	\
2177c478bd9Sstevel@tonic-gate	movq	(src, cnt, 8), %rax;		\
2187c478bd9Sstevel@tonic-gate	movq	0x8(src, cnt, 8), %r8;		\
2197c478bd9Sstevel@tonic-gate	movnti	%rax, (dst, cnt, 8);		\
2207c478bd9Sstevel@tonic-gate	movnti	%r8, 0x8(dst, cnt, 8);		\
2217c478bd9Sstevel@tonic-gate	addq	$2, cnt
2227c478bd9Sstevel@tonic-gate
2237c478bd9Sstevel@tonic-gate	ENTRY(kcopy_nta)
2247c478bd9Sstevel@tonic-gate	pushq	%rbp
2257c478bd9Sstevel@tonic-gate	movq	%rsp, %rbp
2267c478bd9Sstevel@tonic-gate#ifdef DEBUG
227ae115bc7Smrj	cmpq	postbootkernelbase(%rip), %rdi 		/* %rdi = from */
2287c478bd9Sstevel@tonic-gate	jb	0f
229ae115bc7Smrj	cmpq	postbootkernelbase(%rip), %rsi		/* %rsi = to */
2307c478bd9Sstevel@tonic-gate	jnb	1f
2317c478bd9Sstevel@tonic-gate0:	leaq	.kcopy_panic_msg(%rip), %rdi
2327c478bd9Sstevel@tonic-gate	xorl	%eax, %eax
2337c478bd9Sstevel@tonic-gate	call	panic
2347c478bd9Sstevel@tonic-gate1:
2357c478bd9Sstevel@tonic-gate#endif
2367c478bd9Sstevel@tonic-gate
2377c478bd9Sstevel@tonic-gate	movq	%gs:CPU_THREAD, %r9
2387c478bd9Sstevel@tonic-gate	cmpq	$0, %rcx		/* No non-temporal access? */
2397c478bd9Sstevel@tonic-gate	/*
2407c478bd9Sstevel@tonic-gate	 * pass lofault value as 4th argument to do_copy_fault
2417c478bd9Sstevel@tonic-gate	 */
2427c478bd9Sstevel@tonic-gate	leaq	_kcopy_nta_copyerr(%rip), %rcx	/* doesn't set rflags */
2437c478bd9Sstevel@tonic-gate	jnz	do_copy_fault		/* use regular access */
2447c478bd9Sstevel@tonic-gate	/*
2457c478bd9Sstevel@tonic-gate	 * Make sure cnt is >= KCOPY_MIN_SIZE
2467c478bd9Sstevel@tonic-gate	 */
2477c478bd9Sstevel@tonic-gate	cmpq	$KCOPY_MIN_SIZE, %rdx
2487c478bd9Sstevel@tonic-gate	jb	do_copy_fault
2497c478bd9Sstevel@tonic-gate
2507c478bd9Sstevel@tonic-gate	/*
2517c478bd9Sstevel@tonic-gate	 * Make sure src and dst are NTA_ALIGN_SIZE aligned,
2527c478bd9Sstevel@tonic-gate	 * count is COUNT_ALIGN_SIZE aligned.
2537c478bd9Sstevel@tonic-gate	 */
2547c478bd9Sstevel@tonic-gate	movq	%rdi, %r10
2557c478bd9Sstevel@tonic-gate	orq	%rsi, %r10
2567c478bd9Sstevel@tonic-gate	andq	$NTA_ALIGN_MASK, %r10
2577c478bd9Sstevel@tonic-gate	orq	%rdx, %r10
2587c478bd9Sstevel@tonic-gate	andq	$COUNT_ALIGN_MASK, %r10
2597c478bd9Sstevel@tonic-gate	jnz	do_copy_fault
2607c478bd9Sstevel@tonic-gate
2617c478bd9Sstevel@tonic-gate	ALTENTRY(do_copy_fault_nta)
2627c478bd9Sstevel@tonic-gate	movq    %gs:CPU_THREAD, %r9     /* %r9 = thread addr */
2637c478bd9Sstevel@tonic-gate	movq    T_LOFAULT(%r9), %r11    /* save the current lofault */
2647c478bd9Sstevel@tonic-gate	movq    %rcx, T_LOFAULT(%r9)    /* new lofault */
2657c478bd9Sstevel@tonic-gate
2667c478bd9Sstevel@tonic-gate	/*
2677c478bd9Sstevel@tonic-gate	 * COPY_LOOP_BODY uses %rax and %r8
2687c478bd9Sstevel@tonic-gate	 */
2697c478bd9Sstevel@tonic-gate	COPY_LOOP_INIT(%rdi, %rsi, %rdx)
2707c478bd9Sstevel@tonic-gate2:	COPY_LOOP_BODY(%rdi, %rsi, %rdx)
2717c478bd9Sstevel@tonic-gate	jnz	2b
2727c478bd9Sstevel@tonic-gate
2737c478bd9Sstevel@tonic-gate	mfence
2747c478bd9Sstevel@tonic-gate	xorl	%eax, %eax		/* return 0 (success) */
2757c478bd9Sstevel@tonic-gate
2767c478bd9Sstevel@tonic-gate_kcopy_nta_copyerr:
2777c478bd9Sstevel@tonic-gate	movq	%r11, T_LOFAULT(%r9)    /* restore original lofault */
2787c478bd9Sstevel@tonic-gate	leave
2797c478bd9Sstevel@tonic-gate	ret
2807c478bd9Sstevel@tonic-gate	SET_SIZE(do_copy_fault_nta)
2817c478bd9Sstevel@tonic-gate	SET_SIZE(kcopy_nta)
2827c478bd9Sstevel@tonic-gate
2837c478bd9Sstevel@tonic-gate#elif defined(__i386)
2847c478bd9Sstevel@tonic-gate
2857c478bd9Sstevel@tonic-gate#define	ARG_FROM	8
2867c478bd9Sstevel@tonic-gate#define	ARG_TO		12
2877c478bd9Sstevel@tonic-gate#define	ARG_COUNT	16
2887c478bd9Sstevel@tonic-gate
2897c478bd9Sstevel@tonic-gate#define	COPY_LOOP_INIT(src, dst, cnt)	\
2907c478bd9Sstevel@tonic-gate	addl	cnt, src;			\
2917c478bd9Sstevel@tonic-gate	addl	cnt, dst;			\
2927c478bd9Sstevel@tonic-gate	shrl	$3, cnt;			\
2937c478bd9Sstevel@tonic-gate	neg	cnt
2947c478bd9Sstevel@tonic-gate
2957c478bd9Sstevel@tonic-gate#define	COPY_LOOP_BODY(src, dst, cnt)	\
2967c478bd9Sstevel@tonic-gate	prefetchnta	0x100(src, cnt, 8);	\
2977c478bd9Sstevel@tonic-gate	movl	(src, cnt, 8), %esi;		\
2987c478bd9Sstevel@tonic-gate	movnti	%esi, (dst, cnt, 8);		\
2997c478bd9Sstevel@tonic-gate	movl	0x4(src, cnt, 8), %esi;		\
3007c478bd9Sstevel@tonic-gate	movnti	%esi, 0x4(dst, cnt, 8);		\
3017c478bd9Sstevel@tonic-gate	movl	0x8(src, cnt, 8), %esi;		\
3027c478bd9Sstevel@tonic-gate	movnti	%esi, 0x8(dst, cnt, 8);		\
3037c478bd9Sstevel@tonic-gate	movl	0xc(src, cnt, 8), %esi;		\
3047c478bd9Sstevel@tonic-gate	movnti	%esi, 0xc(dst, cnt, 8);		\
3057c478bd9Sstevel@tonic-gate	addl	$2, cnt
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate	/*
3087c478bd9Sstevel@tonic-gate	 * kcopy_nta is not implemented for 32-bit as no performance
3097c478bd9Sstevel@tonic-gate	 * improvement was shown.  We simply jump directly to kcopy
3107c478bd9Sstevel@tonic-gate	 * and discard the 4 arguments.
3117c478bd9Sstevel@tonic-gate	 */
3127c478bd9Sstevel@tonic-gate	ENTRY(kcopy_nta)
3137c478bd9Sstevel@tonic-gate	jmp	kcopy
3147c478bd9Sstevel@tonic-gate
3157c478bd9Sstevel@tonic-gate	lea	_kcopy_nta_copyerr, %eax	/* lofault value */
3167c478bd9Sstevel@tonic-gate	ALTENTRY(do_copy_fault_nta)
3177c478bd9Sstevel@tonic-gate	pushl	%ebp
3187c478bd9Sstevel@tonic-gate	movl	%esp, %ebp		/* setup stack frame */
3197c478bd9Sstevel@tonic-gate	pushl	%esi
3207c478bd9Sstevel@tonic-gate	pushl	%edi
3217c478bd9Sstevel@tonic-gate
3227c478bd9Sstevel@tonic-gate	movl	%gs:CPU_THREAD, %edx
3237c478bd9Sstevel@tonic-gate	movl	T_LOFAULT(%edx), %edi
3247c478bd9Sstevel@tonic-gate	pushl	%edi			/* save the current lofault */
3257c478bd9Sstevel@tonic-gate	movl	%eax, T_LOFAULT(%edx)	/* new lofault */
3267c478bd9Sstevel@tonic-gate
3277c478bd9Sstevel@tonic-gate	/* COPY_LOOP_BODY needs to use %esi */
3287c478bd9Sstevel@tonic-gate	movl	ARG_COUNT(%ebp), %ecx
3297c478bd9Sstevel@tonic-gate	movl	ARG_FROM(%ebp), %edi
3307c478bd9Sstevel@tonic-gate	movl	ARG_TO(%ebp), %eax
3317c478bd9Sstevel@tonic-gate	COPY_LOOP_INIT(%edi, %eax, %ecx)
3327c478bd9Sstevel@tonic-gate1:	COPY_LOOP_BODY(%edi, %eax, %ecx)
3337c478bd9Sstevel@tonic-gate	jnz	1b
3347c478bd9Sstevel@tonic-gate	mfence
3357c478bd9Sstevel@tonic-gate
3367c478bd9Sstevel@tonic-gate	xorl	%eax, %eax
3377c478bd9Sstevel@tonic-gate_kcopy_nta_copyerr:
3387c478bd9Sstevel@tonic-gate	popl	%ecx
3397c478bd9Sstevel@tonic-gate	popl	%edi
3407c478bd9Sstevel@tonic-gate	movl	%ecx, T_LOFAULT(%edx)	/* restore the original lofault */
3417c478bd9Sstevel@tonic-gate	popl	%esi
3427c478bd9Sstevel@tonic-gate	leave
3437c478bd9Sstevel@tonic-gate	ret
3447c478bd9Sstevel@tonic-gate	SET_SIZE(do_copy_fault_nta)
3457c478bd9Sstevel@tonic-gate	SET_SIZE(kcopy_nta)
3467c478bd9Sstevel@tonic-gate
3477c478bd9Sstevel@tonic-gate#undef	ARG_FROM
3487c478bd9Sstevel@tonic-gate#undef	ARG_TO
3497c478bd9Sstevel@tonic-gate#undef	ARG_COUNT
3507c478bd9Sstevel@tonic-gate
3517c478bd9Sstevel@tonic-gate#endif	/* __i386 */
3527c478bd9Sstevel@tonic-gate#endif	/* __lint */
3537c478bd9Sstevel@tonic-gate
3547c478bd9Sstevel@tonic-gate#if defined(__lint)
3557c478bd9Sstevel@tonic-gate
3567c478bd9Sstevel@tonic-gate/* ARGSUSED */
3577c478bd9Sstevel@tonic-gatevoid
3587c478bd9Sstevel@tonic-gatebcopy(const void *from, void *to, size_t count)
3597c478bd9Sstevel@tonic-gate{}
3607c478bd9Sstevel@tonic-gate
3617c478bd9Sstevel@tonic-gate#else	/* __lint */
3627c478bd9Sstevel@tonic-gate
3637c478bd9Sstevel@tonic-gate#if defined(__amd64)
3647c478bd9Sstevel@tonic-gate
3657c478bd9Sstevel@tonic-gate	ENTRY(bcopy)
3667c478bd9Sstevel@tonic-gate#ifdef DEBUG
3677c478bd9Sstevel@tonic-gate	orq	%rdx, %rdx		/* %rdx = count */
3687c478bd9Sstevel@tonic-gate	jz	1f
369ae115bc7Smrj	cmpq	postbootkernelbase(%rip), %rdi		/* %rdi = from */
3707c478bd9Sstevel@tonic-gate	jb	0f
371ae115bc7Smrj	cmpq	postbootkernelbase(%rip), %rsi		/* %rsi = to */
3727c478bd9Sstevel@tonic-gate	jnb	1f
3737c478bd9Sstevel@tonic-gate0:	leaq	.bcopy_panic_msg(%rip), %rdi
3747c478bd9Sstevel@tonic-gate	jmp	call_panic		/* setup stack and call panic */
3757c478bd9Sstevel@tonic-gate1:
3767c478bd9Sstevel@tonic-gate#endif
37722cc0e45SBill Holler	/*
37822cc0e45SBill Holler	 * bcopy_altentry() is called from kcopy, i.e., do_copy_fault.
37922cc0e45SBill Holler	 * kcopy assumes that bcopy doesn't touch %r9 and %r11. If bcopy
38022cc0e45SBill Holler	 * uses these registers in future they must be saved and restored.
38122cc0e45SBill Holler	 */
38222cc0e45SBill Holler	ALTENTRY(bcopy_altentry)
3837c478bd9Sstevel@tonic-gatedo_copy:
38422cc0e45SBill Holler#define	L(s) .bcopy/**/s
38522cc0e45SBill Holler	cmpq	$0x50, %rdx		/* 80 */
386*9b6707c5SRobert Mustacchi	jae	bcopy_ck_size
38722cc0e45SBill Holler
38822cc0e45SBill Holler	/*
38922cc0e45SBill Holler	 * Performance data shows many caller's copy small buffers. So for
39022cc0e45SBill Holler	 * best perf for these sizes unrolled code is used. Store data without
39122cc0e45SBill Holler	 * worrying about alignment.
39222cc0e45SBill Holler	 */
39322cc0e45SBill Holler	leaq	L(fwdPxQx)(%rip), %r10
39422cc0e45SBill Holler	addq	%rdx, %rdi
39522cc0e45SBill Holler	addq	%rdx, %rsi
39622cc0e45SBill Holler	movslq	(%r10,%rdx,4), %rcx
39722cc0e45SBill Holler	leaq	(%rcx,%r10,1), %r10
39822cc0e45SBill Holler	jmpq	*%r10
39922cc0e45SBill Holler
40022cc0e45SBill Holler	.p2align 4
40122cc0e45SBill HollerL(fwdPxQx):
40222cc0e45SBill Holler	.int       L(P0Q0)-L(fwdPxQx)	/* 0 */
40322cc0e45SBill Holler	.int       L(P1Q0)-L(fwdPxQx)
40422cc0e45SBill Holler	.int       L(P2Q0)-L(fwdPxQx)
40522cc0e45SBill Holler	.int       L(P3Q0)-L(fwdPxQx)
40622cc0e45SBill Holler	.int       L(P4Q0)-L(fwdPxQx)
40722cc0e45SBill Holler	.int       L(P5Q0)-L(fwdPxQx)
40822cc0e45SBill Holler	.int       L(P6Q0)-L(fwdPxQx)
40922cc0e45SBill Holler	.int       L(P7Q0)-L(fwdPxQx)
41022cc0e45SBill Holler
41122cc0e45SBill Holler	.int       L(P0Q1)-L(fwdPxQx)	/* 8 */
41222cc0e45SBill Holler	.int       L(P1Q1)-L(fwdPxQx)
41322cc0e45SBill Holler	.int       L(P2Q1)-L(fwdPxQx)
41422cc0e45SBill Holler	.int       L(P3Q1)-L(fwdPxQx)
41522cc0e45SBill Holler	.int       L(P4Q1)-L(fwdPxQx)
41622cc0e45SBill Holler	.int       L(P5Q1)-L(fwdPxQx)
41722cc0e45SBill Holler	.int       L(P6Q1)-L(fwdPxQx)
41822cc0e45SBill Holler	.int       L(P7Q1)-L(fwdPxQx)
41922cc0e45SBill Holler
42022cc0e45SBill Holler	.int       L(P0Q2)-L(fwdPxQx)	/* 16 */
42122cc0e45SBill Holler	.int       L(P1Q2)-L(fwdPxQx)
42222cc0e45SBill Holler	.int       L(P2Q2)-L(fwdPxQx)
42322cc0e45SBill Holler	.int       L(P3Q2)-L(fwdPxQx)
42422cc0e45SBill Holler	.int       L(P4Q2)-L(fwdPxQx)
42522cc0e45SBill Holler	.int       L(P5Q2)-L(fwdPxQx)
42622cc0e45SBill Holler	.int       L(P6Q2)-L(fwdPxQx)
42722cc0e45SBill Holler	.int       L(P7Q2)-L(fwdPxQx)
42822cc0e45SBill Holler
42922cc0e45SBill Holler	.int       L(P0Q3)-L(fwdPxQx)	/* 24 */
43022cc0e45SBill Holler	.int       L(P1Q3)-L(fwdPxQx)
43122cc0e45SBill Holler	.int       L(P2Q3)-L(fwdPxQx)
43222cc0e45SBill Holler	.int       L(P3Q3)-L(fwdPxQx)
43322cc0e45SBill Holler	.int       L(P4Q3)-L(fwdPxQx)
43422cc0e45SBill Holler	.int       L(P5Q3)-L(fwdPxQx)
43522cc0e45SBill Holler	.int       L(P6Q3)-L(fwdPxQx)
43622cc0e45SBill Holler	.int       L(P7Q3)-L(fwdPxQx)
43722cc0e45SBill Holler
43822cc0e45SBill Holler	.int       L(P0Q4)-L(fwdPxQx)	/* 32 */
43922cc0e45SBill Holler	.int       L(P1Q4)-L(fwdPxQx)
44022cc0e45SBill Holler	.int       L(P2Q4)-L(fwdPxQx)
44122cc0e45SBill Holler	.int       L(P3Q4)-L(fwdPxQx)
44222cc0e45SBill Holler	.int       L(P4Q4)-L(fwdPxQx)
44322cc0e45SBill Holler	.int       L(P5Q4)-L(fwdPxQx)
44422cc0e45SBill Holler	.int       L(P6Q4)-L(fwdPxQx)
44522cc0e45SBill Holler	.int       L(P7Q4)-L(fwdPxQx)
44622cc0e45SBill Holler
44722cc0e45SBill Holler	.int       L(P0Q5)-L(fwdPxQx)	/* 40 */
44822cc0e45SBill Holler	.int       L(P1Q5)-L(fwdPxQx)
44922cc0e45SBill Holler	.int       L(P2Q5)-L(fwdPxQx)
45022cc0e45SBill Holler	.int       L(P3Q5)-L(fwdPxQx)
45122cc0e45SBill Holler	.int       L(P4Q5)-L(fwdPxQx)
45222cc0e45SBill Holler	.int       L(P5Q5)-L(fwdPxQx)
45322cc0e45SBill Holler	.int       L(P6Q5)-L(fwdPxQx)
45422cc0e45SBill Holler	.int       L(P7Q5)-L(fwdPxQx)
45522cc0e45SBill Holler
45622cc0e45SBill Holler	.int       L(P0Q6)-L(fwdPxQx)	/* 48 */
45722cc0e45SBill Holler	.int       L(P1Q6)-L(fwdPxQx)
45822cc0e45SBill Holler	.int       L(P2Q6)-L(fwdPxQx)
45922cc0e45SBill Holler	.int       L(P3Q6)-L(fwdPxQx)
46022cc0e45SBill Holler	.int       L(P4Q6)-L(fwdPxQx)
46122cc0e45SBill Holler	.int       L(P5Q6)-L(fwdPxQx)
46222cc0e45SBill Holler	.int       L(P6Q6)-L(fwdPxQx)
46322cc0e45SBill Holler	.int       L(P7Q6)-L(fwdPxQx)
46422cc0e45SBill Holler
46522cc0e45SBill Holler	.int       L(P0Q7)-L(fwdPxQx)	/* 56 */
46622cc0e45SBill Holler	.int       L(P1Q7)-L(fwdPxQx)
46722cc0e45SBill Holler	.int       L(P2Q7)-L(fwdPxQx)
46822cc0e45SBill Holler	.int       L(P3Q7)-L(fwdPxQx)
46922cc0e45SBill Holler	.int       L(P4Q7)-L(fwdPxQx)
47022cc0e45SBill Holler	.int       L(P5Q7)-L(fwdPxQx)
47122cc0e45SBill Holler	.int       L(P6Q7)-L(fwdPxQx)
47222cc0e45SBill Holler	.int       L(P7Q7)-L(fwdPxQx)
47322cc0e45SBill Holler
47422cc0e45SBill Holler	.int       L(P0Q8)-L(fwdPxQx)	/* 64 */
47522cc0e45SBill Holler	.int       L(P1Q8)-L(fwdPxQx)
47622cc0e45SBill Holler	.int       L(P2Q8)-L(fwdPxQx)
47722cc0e45SBill Holler	.int       L(P3Q8)-L(fwdPxQx)
47822cc0e45SBill Holler	.int       L(P4Q8)-L(fwdPxQx)
47922cc0e45SBill Holler	.int       L(P5Q8)-L(fwdPxQx)
48022cc0e45SBill Holler	.int       L(P6Q8)-L(fwdPxQx)
48122cc0e45SBill Holler	.int       L(P7Q8)-L(fwdPxQx)
48222cc0e45SBill Holler
48322cc0e45SBill Holler	.int       L(P0Q9)-L(fwdPxQx)	/* 72 */
48422cc0e45SBill Holler	.int       L(P1Q9)-L(fwdPxQx)
48522cc0e45SBill Holler	.int       L(P2Q9)-L(fwdPxQx)
48622cc0e45SBill Holler	.int       L(P3Q9)-L(fwdPxQx)
48722cc0e45SBill Holler	.int       L(P4Q9)-L(fwdPxQx)
48822cc0e45SBill Holler	.int       L(P5Q9)-L(fwdPxQx)
48922cc0e45SBill Holler	.int       L(P6Q9)-L(fwdPxQx)
49022cc0e45SBill Holler	.int       L(P7Q9)-L(fwdPxQx)	/* 79 */
49122cc0e45SBill Holler
49222cc0e45SBill Holler	.p2align 4
49322cc0e45SBill HollerL(P0Q9):
49422cc0e45SBill Holler	mov    -0x48(%rdi), %rcx
49522cc0e45SBill Holler	mov    %rcx, -0x48(%rsi)
49622cc0e45SBill HollerL(P0Q8):
49722cc0e45SBill Holler	mov    -0x40(%rdi), %r10
49822cc0e45SBill Holler	mov    %r10, -0x40(%rsi)
49922cc0e45SBill HollerL(P0Q7):
50022cc0e45SBill Holler	mov    -0x38(%rdi), %r8
50122cc0e45SBill Holler	mov    %r8, -0x38(%rsi)
50222cc0e45SBill HollerL(P0Q6):
50322cc0e45SBill Holler	mov    -0x30(%rdi), %rcx
50422cc0e45SBill Holler	mov    %rcx, -0x30(%rsi)
50522cc0e45SBill HollerL(P0Q5):
50622cc0e45SBill Holler	mov    -0x28(%rdi), %r10
50722cc0e45SBill Holler	mov    %r10, -0x28(%rsi)
50822cc0e45SBill HollerL(P0Q4):
50922cc0e45SBill Holler	mov    -0x20(%rdi), %r8
51022cc0e45SBill Holler	mov    %r8, -0x20(%rsi)
51122cc0e45SBill HollerL(P0Q3):
51222cc0e45SBill Holler	mov    -0x18(%rdi), %rcx
51322cc0e45SBill Holler	mov    %rcx, -0x18(%rsi)
51422cc0e45SBill HollerL(P0Q2):
51522cc0e45SBill Holler	mov    -0x10(%rdi), %r10
51622cc0e45SBill Holler	mov    %r10, -0x10(%rsi)
51722cc0e45SBill HollerL(P0Q1):
51822cc0e45SBill Holler	mov    -0x8(%rdi), %r8
51922cc0e45SBill Holler	mov    %r8, -0x8(%rsi)
52022cc0e45SBill HollerL(P0Q0):
52122cc0e45SBill Holler	ret
52222cc0e45SBill Holler
52322cc0e45SBill Holler	.p2align 4
52422cc0e45SBill HollerL(P1Q9):
52522cc0e45SBill Holler	mov    -0x49(%rdi), %r8
52622cc0e45SBill Holler	mov    %r8, -0x49(%rsi)
52722cc0e45SBill HollerL(P1Q8):
52822cc0e45SBill Holler	mov    -0x41(%rdi), %rcx
52922cc0e45SBill Holler	mov    %rcx, -0x41(%rsi)
53022cc0e45SBill HollerL(P1Q7):
53122cc0e45SBill Holler	mov    -0x39(%rdi), %r10
53222cc0e45SBill Holler	mov    %r10, -0x39(%rsi)
53322cc0e45SBill HollerL(P1Q6):
53422cc0e45SBill Holler	mov    -0x31(%rdi), %r8
53522cc0e45SBill Holler	mov    %r8, -0x31(%rsi)
53622cc0e45SBill HollerL(P1Q5):
53722cc0e45SBill Holler	mov    -0x29(%rdi), %rcx
53822cc0e45SBill Holler	mov    %rcx, -0x29(%rsi)
53922cc0e45SBill HollerL(P1Q4):
54022cc0e45SBill Holler	mov    -0x21(%rdi), %r10
54122cc0e45SBill Holler	mov    %r10, -0x21(%rsi)
54222cc0e45SBill HollerL(P1Q3):
54322cc0e45SBill Holler	mov    -0x19(%rdi), %r8
54422cc0e45SBill Holler	mov    %r8, -0x19(%rsi)
54522cc0e45SBill HollerL(P1Q2):
54622cc0e45SBill Holler	mov    -0x11(%rdi), %rcx
54722cc0e45SBill Holler	mov    %rcx, -0x11(%rsi)
54822cc0e45SBill HollerL(P1Q1):
54922cc0e45SBill Holler	mov    -0x9(%rdi), %r10
55022cc0e45SBill Holler	mov    %r10, -0x9(%rsi)
55122cc0e45SBill HollerL(P1Q0):
55222cc0e45SBill Holler	movzbq -0x1(%rdi), %r8
55322cc0e45SBill Holler	mov    %r8b, -0x1(%rsi)
55422cc0e45SBill Holler	ret
55522cc0e45SBill Holler
55622cc0e45SBill Holler	.p2align 4
55722cc0e45SBill HollerL(P2Q9):
55822cc0e45SBill Holler	mov    -0x4a(%rdi), %r8
55922cc0e45SBill Holler	mov    %r8, -0x4a(%rsi)
56022cc0e45SBill HollerL(P2Q8):
56122cc0e45SBill Holler	mov    -0x42(%rdi), %rcx
56222cc0e45SBill Holler	mov    %rcx, -0x42(%rsi)
56322cc0e45SBill HollerL(P2Q7):
56422cc0e45SBill Holler	mov    -0x3a(%rdi), %r10
56522cc0e45SBill Holler	mov    %r10, -0x3a(%rsi)
56622cc0e45SBill HollerL(P2Q6):
56722cc0e45SBill Holler	mov    -0x32(%rdi), %r8
56822cc0e45SBill Holler	mov    %r8, -0x32(%rsi)
56922cc0e45SBill HollerL(P2Q5):
57022cc0e45SBill Holler	mov    -0x2a(%rdi), %rcx
57122cc0e45SBill Holler	mov    %rcx, -0x2a(%rsi)
57222cc0e45SBill HollerL(P2Q4):
57322cc0e45SBill Holler	mov    -0x22(%rdi), %r10
57422cc0e45SBill Holler	mov    %r10, -0x22(%rsi)
57522cc0e45SBill HollerL(P2Q3):
57622cc0e45SBill Holler	mov    -0x1a(%rdi), %r8
57722cc0e45SBill Holler	mov    %r8, -0x1a(%rsi)
57822cc0e45SBill HollerL(P2Q2):
57922cc0e45SBill Holler	mov    -0x12(%rdi), %rcx
58022cc0e45SBill Holler	mov    %rcx, -0x12(%rsi)
58122cc0e45SBill HollerL(P2Q1):
58222cc0e45SBill Holler	mov    -0xa(%rdi), %r10
58322cc0e45SBill Holler	mov    %r10, -0xa(%rsi)
58422cc0e45SBill HollerL(P2Q0):
58522cc0e45SBill Holler	movzwq -0x2(%rdi), %r8
58622cc0e45SBill Holler	mov    %r8w, -0x2(%rsi)
58722cc0e45SBill Holler	ret
58822cc0e45SBill Holler
58922cc0e45SBill Holler	.p2align 4
59022cc0e45SBill HollerL(P3Q9):
59122cc0e45SBill Holler	mov    -0x4b(%rdi), %r8
59222cc0e45SBill Holler	mov    %r8, -0x4b(%rsi)
59322cc0e45SBill HollerL(P3Q8):
59422cc0e45SBill Holler	mov    -0x43(%rdi), %rcx
59522cc0e45SBill Holler	mov    %rcx, -0x43(%rsi)
59622cc0e45SBill HollerL(P3Q7):
59722cc0e45SBill Holler	mov    -0x3b(%rdi), %r10
59822cc0e45SBill Holler	mov    %r10, -0x3b(%rsi)
59922cc0e45SBill HollerL(P3Q6):
60022cc0e45SBill Holler	mov    -0x33(%rdi), %r8
60122cc0e45SBill Holler	mov    %r8, -0x33(%rsi)
60222cc0e45SBill HollerL(P3Q5):
60322cc0e45SBill Holler	mov    -0x2b(%rdi), %rcx
60422cc0e45SBill Holler	mov    %rcx, -0x2b(%rsi)
60522cc0e45SBill HollerL(P3Q4):
60622cc0e45SBill Holler	mov    -0x23(%rdi), %r10
60722cc0e45SBill Holler	mov    %r10, -0x23(%rsi)
60822cc0e45SBill HollerL(P3Q3):
60922cc0e45SBill Holler	mov    -0x1b(%rdi), %r8
61022cc0e45SBill Holler	mov    %r8, -0x1b(%rsi)
61122cc0e45SBill HollerL(P3Q2):
61222cc0e45SBill Holler	mov    -0x13(%rdi), %rcx
61322cc0e45SBill Holler	mov    %rcx, -0x13(%rsi)
61422cc0e45SBill HollerL(P3Q1):
61522cc0e45SBill Holler	mov    -0xb(%rdi), %r10
61622cc0e45SBill Holler	mov    %r10, -0xb(%rsi)
61722cc0e45SBill Holler	/*
61822cc0e45SBill Holler	 * These trailing loads/stores have to do all their loads 1st,
61922cc0e45SBill Holler	 * then do the stores.
62022cc0e45SBill Holler	 */
62122cc0e45SBill HollerL(P3Q0):
62222cc0e45SBill Holler	movzwq -0x3(%rdi), %r8
62322cc0e45SBill Holler	movzbq -0x1(%rdi), %r10
62422cc0e45SBill Holler	mov    %r8w, -0x3(%rsi)
62522cc0e45SBill Holler	mov    %r10b, -0x1(%rsi)
62622cc0e45SBill Holler	ret
62722cc0e45SBill Holler
62822cc0e45SBill Holler	.p2align 4
62922cc0e45SBill HollerL(P4Q9):
63022cc0e45SBill Holler	mov    -0x4c(%rdi), %r8
63122cc0e45SBill Holler	mov    %r8, -0x4c(%rsi)
63222cc0e45SBill HollerL(P4Q8):
63322cc0e45SBill Holler	mov    -0x44(%rdi), %rcx
63422cc0e45SBill Holler	mov    %rcx, -0x44(%rsi)
63522cc0e45SBill HollerL(P4Q7):
63622cc0e45SBill Holler	mov    -0x3c(%rdi), %r10
63722cc0e45SBill Holler	mov    %r10, -0x3c(%rsi)
63822cc0e45SBill HollerL(P4Q6):
63922cc0e45SBill Holler	mov    -0x34(%rdi), %r8
64022cc0e45SBill Holler	mov    %r8, -0x34(%rsi)
64122cc0e45SBill HollerL(P4Q5):
64222cc0e45SBill Holler	mov    -0x2c(%rdi), %rcx
64322cc0e45SBill Holler	mov    %rcx, -0x2c(%rsi)
64422cc0e45SBill HollerL(P4Q4):
64522cc0e45SBill Holler	mov    -0x24(%rdi), %r10
64622cc0e45SBill Holler	mov    %r10, -0x24(%rsi)
64722cc0e45SBill HollerL(P4Q3):
64822cc0e45SBill Holler	mov    -0x1c(%rdi), %r8
64922cc0e45SBill Holler	mov    %r8, -0x1c(%rsi)
65022cc0e45SBill HollerL(P4Q2):
65122cc0e45SBill Holler	mov    -0x14(%rdi), %rcx
65222cc0e45SBill Holler	mov    %rcx, -0x14(%rsi)
65322cc0e45SBill HollerL(P4Q1):
65422cc0e45SBill Holler	mov    -0xc(%rdi), %r10
65522cc0e45SBill Holler	mov    %r10, -0xc(%rsi)
65622cc0e45SBill HollerL(P4Q0):
65722cc0e45SBill Holler	mov    -0x4(%rdi), %r8d
65822cc0e45SBill Holler	mov    %r8d, -0x4(%rsi)
65922cc0e45SBill Holler	ret
66022cc0e45SBill Holler
66122cc0e45SBill Holler	.p2align 4
66222cc0e45SBill HollerL(P5Q9):
66322cc0e45SBill Holler	mov    -0x4d(%rdi), %r8
66422cc0e45SBill Holler	mov    %r8, -0x4d(%rsi)
66522cc0e45SBill HollerL(P5Q8):
66622cc0e45SBill Holler	mov    -0x45(%rdi), %rcx
66722cc0e45SBill Holler	mov    %rcx, -0x45(%rsi)
66822cc0e45SBill HollerL(P5Q7):
66922cc0e45SBill Holler	mov    -0x3d(%rdi), %r10
67022cc0e45SBill Holler	mov    %r10, -0x3d(%rsi)
67122cc0e45SBill HollerL(P5Q6):
67222cc0e45SBill Holler	mov    -0x35(%rdi), %r8
67322cc0e45SBill Holler	mov    %r8, -0x35(%rsi)
67422cc0e45SBill HollerL(P5Q5):
67522cc0e45SBill Holler	mov    -0x2d(%rdi), %rcx
67622cc0e45SBill Holler	mov    %rcx, -0x2d(%rsi)
67722cc0e45SBill HollerL(P5Q4):
67822cc0e45SBill Holler	mov    -0x25(%rdi), %r10
67922cc0e45SBill Holler	mov    %r10, -0x25(%rsi)
68022cc0e45SBill HollerL(P5Q3):
68122cc0e45SBill Holler	mov    -0x1d(%rdi), %r8
68222cc0e45SBill Holler	mov    %r8, -0x1d(%rsi)
68322cc0e45SBill HollerL(P5Q2):
68422cc0e45SBill Holler	mov    -0x15(%rdi), %rcx
68522cc0e45SBill Holler	mov    %rcx, -0x15(%rsi)
68622cc0e45SBill HollerL(P5Q1):
68722cc0e45SBill Holler	mov    -0xd(%rdi), %r10
68822cc0e45SBill Holler	mov    %r10, -0xd(%rsi)
68922cc0e45SBill HollerL(P5Q0):
69022cc0e45SBill Holler	mov    -0x5(%rdi), %r8d
69122cc0e45SBill Holler	movzbq -0x1(%rdi), %r10
69222cc0e45SBill Holler	mov    %r8d, -0x5(%rsi)
69322cc0e45SBill Holler	mov    %r10b, -0x1(%rsi)
69422cc0e45SBill Holler	ret
69522cc0e45SBill Holler
69622cc0e45SBill Holler	.p2align 4
69722cc0e45SBill HollerL(P6Q9):
69822cc0e45SBill Holler	mov    -0x4e(%rdi), %r8
69922cc0e45SBill Holler	mov    %r8, -0x4e(%rsi)
70022cc0e45SBill HollerL(P6Q8):
70122cc0e45SBill Holler	mov    -0x46(%rdi), %rcx
70222cc0e45SBill Holler	mov    %rcx, -0x46(%rsi)
70322cc0e45SBill HollerL(P6Q7):
70422cc0e45SBill Holler	mov    -0x3e(%rdi), %r10
70522cc0e45SBill Holler	mov    %r10, -0x3e(%rsi)
70622cc0e45SBill HollerL(P6Q6):
70722cc0e45SBill Holler	mov    -0x36(%rdi), %r8
70822cc0e45SBill Holler	mov    %r8, -0x36(%rsi)
70922cc0e45SBill HollerL(P6Q5):
71022cc0e45SBill Holler	mov    -0x2e(%rdi), %rcx
71122cc0e45SBill Holler	mov    %rcx, -0x2e(%rsi)
71222cc0e45SBill HollerL(P6Q4):
71322cc0e45SBill Holler	mov    -0x26(%rdi), %r10
71422cc0e45SBill Holler	mov    %r10, -0x26(%rsi)
71522cc0e45SBill HollerL(P6Q3):
71622cc0e45SBill Holler	mov    -0x1e(%rdi), %r8
71722cc0e45SBill Holler	mov    %r8, -0x1e(%rsi)
71822cc0e45SBill HollerL(P6Q2):
71922cc0e45SBill Holler	mov    -0x16(%rdi), %rcx
72022cc0e45SBill Holler	mov    %rcx, -0x16(%rsi)
72122cc0e45SBill HollerL(P6Q1):
72222cc0e45SBill Holler	mov    -0xe(%rdi), %r10
72322cc0e45SBill Holler	mov    %r10, -0xe(%rsi)
72422cc0e45SBill HollerL(P6Q0):
72522cc0e45SBill Holler	mov    -0x6(%rdi), %r8d
72622cc0e45SBill Holler	movzwq -0x2(%rdi), %r10
72722cc0e45SBill Holler	mov    %r8d, -0x6(%rsi)
72822cc0e45SBill Holler	mov    %r10w, -0x2(%rsi)
72922cc0e45SBill Holler	ret
73022cc0e45SBill Holler
73122cc0e45SBill Holler	.p2align 4
73222cc0e45SBill HollerL(P7Q9):
73322cc0e45SBill Holler	mov    -0x4f(%rdi), %r8
73422cc0e45SBill Holler	mov    %r8, -0x4f(%rsi)
73522cc0e45SBill HollerL(P7Q8):
73622cc0e45SBill Holler	mov    -0x47(%rdi), %rcx
73722cc0e45SBill Holler	mov    %rcx, -0x47(%rsi)
73822cc0e45SBill HollerL(P7Q7):
73922cc0e45SBill Holler	mov    -0x3f(%rdi), %r10
74022cc0e45SBill Holler	mov    %r10, -0x3f(%rsi)
74122cc0e45SBill HollerL(P7Q6):
74222cc0e45SBill Holler	mov    -0x37(%rdi), %r8
74322cc0e45SBill Holler	mov    %r8, -0x37(%rsi)
74422cc0e45SBill HollerL(P7Q5):
74522cc0e45SBill Holler	mov    -0x2f(%rdi), %rcx
74622cc0e45SBill Holler	mov    %rcx, -0x2f(%rsi)
74722cc0e45SBill HollerL(P7Q4):
74822cc0e45SBill Holler	mov    -0x27(%rdi), %r10
74922cc0e45SBill Holler	mov    %r10, -0x27(%rsi)
75022cc0e45SBill HollerL(P7Q3):
75122cc0e45SBill Holler	mov    -0x1f(%rdi), %r8
75222cc0e45SBill Holler	mov    %r8, -0x1f(%rsi)
75322cc0e45SBill HollerL(P7Q2):
75422cc0e45SBill Holler	mov    -0x17(%rdi), %rcx
75522cc0e45SBill Holler	mov    %rcx, -0x17(%rsi)
75622cc0e45SBill HollerL(P7Q1):
75722cc0e45SBill Holler	mov    -0xf(%rdi), %r10
75822cc0e45SBill Holler	mov    %r10, -0xf(%rsi)
75922cc0e45SBill HollerL(P7Q0):
76022cc0e45SBill Holler	mov    -0x7(%rdi), %r8d
76122cc0e45SBill Holler	movzwq -0x3(%rdi), %r10
76222cc0e45SBill Holler	movzbq -0x1(%rdi), %rcx
76322cc0e45SBill Holler	mov    %r8d, -0x7(%rsi)
76422cc0e45SBill Holler	mov    %r10w, -0x3(%rsi)
76522cc0e45SBill Holler	mov    %cl, -0x1(%rsi)
76622cc0e45SBill Holler	ret
76722cc0e45SBill Holler
76822cc0e45SBill Holler	/*
76922cc0e45SBill Holler	 * For large sizes rep smovq is fastest.
77022cc0e45SBill Holler	 * Transition point determined experimentally as measured on
77122cc0e45SBill Holler	 * Intel Xeon processors (incl. Nehalem and previous generations) and
77222cc0e45SBill Holler	 * AMD Opteron. The transition value is patched at boot time to avoid
77322cc0e45SBill Holler	 * memory reference hit.
77422cc0e45SBill Holler	 */
77522cc0e45SBill Holler	.globl bcopy_patch_start
77622cc0e45SBill Hollerbcopy_patch_start:
77722cc0e45SBill Holler	cmpq	$BCOPY_NHM_REP, %rdx
77822cc0e45SBill Holler	.globl bcopy_patch_end
77922cc0e45SBill Hollerbcopy_patch_end:
78022cc0e45SBill Holler
78122cc0e45SBill Holler	.p2align 4
78222cc0e45SBill Holler	.globl bcopy_ck_size
78322cc0e45SBill Hollerbcopy_ck_size:
78422cc0e45SBill Holler	cmpq	$BCOPY_DFLT_REP, %rdx
785*9b6707c5SRobert Mustacchi	jae	L(use_rep)
78622cc0e45SBill Holler
78722cc0e45SBill Holler	/*
78822cc0e45SBill Holler	 * Align to a 8-byte boundary. Avoids penalties from unaligned stores
78922cc0e45SBill Holler	 * as well as from stores spanning cachelines.
79022cc0e45SBill Holler	 */
79122cc0e45SBill Holler	test	$0x7, %rsi
79222cc0e45SBill Holler	jz	L(aligned_loop)
79322cc0e45SBill Holler	test	$0x1, %rsi
79422cc0e45SBill Holler	jz	2f
79522cc0e45SBill Holler	movzbq	(%rdi), %r8
79622cc0e45SBill Holler	dec	%rdx
79722cc0e45SBill Holler	inc	%rdi
79822cc0e45SBill Holler	mov	%r8b, (%rsi)
79922cc0e45SBill Holler	inc	%rsi
80022cc0e45SBill Holler2:
80122cc0e45SBill Holler	test	$0x2, %rsi
80222cc0e45SBill Holler	jz	4f
80322cc0e45SBill Holler	movzwq	(%rdi), %r8
80422cc0e45SBill Holler	sub	$0x2, %rdx
80522cc0e45SBill Holler	add	$0x2, %rdi
80622cc0e45SBill Holler	mov	%r8w, (%rsi)
80722cc0e45SBill Holler	add	$0x2, %rsi
80822cc0e45SBill Holler4:
80922cc0e45SBill Holler	test	$0x4, %rsi
81022cc0e45SBill Holler	jz	L(aligned_loop)
81122cc0e45SBill Holler	mov	(%rdi), %r8d
81222cc0e45SBill Holler	sub	$0x4, %rdx
81322cc0e45SBill Holler	add	$0x4, %rdi
81422cc0e45SBill Holler	mov	%r8d, (%rsi)
81522cc0e45SBill Holler	add	$0x4, %rsi
81622cc0e45SBill Holler
81722cc0e45SBill Holler	/*
81822cc0e45SBill Holler	 * Copy 64-bytes per loop
81922cc0e45SBill Holler	 */
82022cc0e45SBill Holler	.p2align 4
82122cc0e45SBill HollerL(aligned_loop):
82222cc0e45SBill Holler	mov	(%rdi), %r8
82322cc0e45SBill Holler	mov	0x8(%rdi), %r10
82422cc0e45SBill Holler	lea	-0x40(%rdx), %rdx
82522cc0e45SBill Holler	mov	%r8, (%rsi)
82622cc0e45SBill Holler	mov	%r10, 0x8(%rsi)
82722cc0e45SBill Holler	mov	0x10(%rdi), %rcx
82822cc0e45SBill Holler	mov	0x18(%rdi), %r8
82922cc0e45SBill Holler	mov	%rcx, 0x10(%rsi)
83022cc0e45SBill Holler	mov	%r8, 0x18(%rsi)
83122cc0e45SBill Holler
83222cc0e45SBill Holler	cmp	$0x40, %rdx
83322cc0e45SBill Holler	mov	0x20(%rdi), %r10
83422cc0e45SBill Holler	mov	0x28(%rdi), %rcx
83522cc0e45SBill Holler	mov	%r10, 0x20(%rsi)
83622cc0e45SBill Holler	mov	%rcx, 0x28(%rsi)
83722cc0e45SBill Holler	mov	0x30(%rdi), %r8
83822cc0e45SBill Holler	mov	0x38(%rdi), %r10
83922cc0e45SBill Holler	lea	0x40(%rdi), %rdi
84022cc0e45SBill Holler	mov	%r8, 0x30(%rsi)
84122cc0e45SBill Holler	mov	%r10, 0x38(%rsi)
84222cc0e45SBill Holler	lea	0x40(%rsi), %rsi
843*9b6707c5SRobert Mustacchi	jae	L(aligned_loop)
84422cc0e45SBill Holler
84522cc0e45SBill Holler	/*
84622cc0e45SBill Holler	 * Copy remaining bytes (0-63)
84722cc0e45SBill Holler	 */
84822cc0e45SBill HollerL(do_remainder):
84922cc0e45SBill Holler	leaq	L(fwdPxQx)(%rip), %r10
85022cc0e45SBill Holler	addq	%rdx, %rdi
85122cc0e45SBill Holler	addq	%rdx, %rsi
85222cc0e45SBill Holler	movslq	(%r10,%rdx,4), %rcx
85322cc0e45SBill Holler	leaq	(%rcx,%r10,1), %r10
85422cc0e45SBill Holler	jmpq	*%r10
85522cc0e45SBill Holler
85622cc0e45SBill Holler	/*
85722cc0e45SBill Holler	 * Use rep smovq. Clear remainder via unrolled code
85822cc0e45SBill Holler	 */
85922cc0e45SBill Holler	.p2align 4
86022cc0e45SBill HollerL(use_rep):
8617c478bd9Sstevel@tonic-gate	xchgq	%rdi, %rsi		/* %rsi = source, %rdi = destination */
8627c478bd9Sstevel@tonic-gate	movq	%rdx, %rcx		/* %rcx = count */
8637c478bd9Sstevel@tonic-gate	shrq	$3, %rcx		/* 8-byte word count */
8647c478bd9Sstevel@tonic-gate	rep
8657c478bd9Sstevel@tonic-gate	  smovq
8667c478bd9Sstevel@tonic-gate
86722cc0e45SBill Holler	xchgq	%rsi, %rdi		/* %rdi = src, %rsi = destination */
86822cc0e45SBill Holler	andq	$7, %rdx		/* remainder */
86922cc0e45SBill Holler	jnz	L(do_remainder)
8707c478bd9Sstevel@tonic-gate	ret
87122cc0e45SBill Holler#undef	L
8727c478bd9Sstevel@tonic-gate
8737c478bd9Sstevel@tonic-gate#ifdef DEBUG
8747c478bd9Sstevel@tonic-gate	/*
8757c478bd9Sstevel@tonic-gate	 * Setup frame on the run-time stack. The end of the input argument
8767c478bd9Sstevel@tonic-gate	 * area must be aligned on a 16 byte boundary. The stack pointer %rsp,
8777c478bd9Sstevel@tonic-gate	 * always points to the end of the latest allocated stack frame.
8787c478bd9Sstevel@tonic-gate	 * panic(const char *format, ...) is a varargs function. When a
8797c478bd9Sstevel@tonic-gate	 * function taking variable arguments is called, %rax must be set
8807c478bd9Sstevel@tonic-gate	 * to eight times the number of floating point parameters passed
8817c478bd9Sstevel@tonic-gate	 * to the function in SSE registers.
8827c478bd9Sstevel@tonic-gate	 */
8837c478bd9Sstevel@tonic-gatecall_panic:
8847c478bd9Sstevel@tonic-gate	pushq	%rbp			/* align stack properly */
8857c478bd9Sstevel@tonic-gate	movq	%rsp, %rbp
8867c478bd9Sstevel@tonic-gate	xorl	%eax, %eax		/* no variable arguments */
8877c478bd9Sstevel@tonic-gate	call	panic			/* %rdi = format string */
8887c478bd9Sstevel@tonic-gate#endif
88922cc0e45SBill Holler	SET_SIZE(bcopy_altentry)
8907c478bd9Sstevel@tonic-gate	SET_SIZE(bcopy)
8917c478bd9Sstevel@tonic-gate
8927c478bd9Sstevel@tonic-gate#elif defined(__i386)
8937c478bd9Sstevel@tonic-gate
8947c478bd9Sstevel@tonic-gate#define	ARG_FROM	4
8957c478bd9Sstevel@tonic-gate#define	ARG_TO		8
8967c478bd9Sstevel@tonic-gate#define	ARG_COUNT	12
8977c478bd9Sstevel@tonic-gate
8987c478bd9Sstevel@tonic-gate	ENTRY(bcopy)
8997c478bd9Sstevel@tonic-gate#ifdef DEBUG
9007c478bd9Sstevel@tonic-gate	movl	ARG_COUNT(%esp), %eax
9017c478bd9Sstevel@tonic-gate	orl	%eax, %eax
9027c478bd9Sstevel@tonic-gate	jz	1f
903ae115bc7Smrj	movl	postbootkernelbase, %eax
9047c478bd9Sstevel@tonic-gate	cmpl	%eax, ARG_FROM(%esp)
9057c478bd9Sstevel@tonic-gate	jb	0f
9067c478bd9Sstevel@tonic-gate	cmpl	%eax, ARG_TO(%esp)
9077c478bd9Sstevel@tonic-gate	jnb	1f
9087c478bd9Sstevel@tonic-gate0:	pushl	%ebp
9097c478bd9Sstevel@tonic-gate	movl	%esp, %ebp
9107c478bd9Sstevel@tonic-gate	pushl	$.bcopy_panic_msg
9117c478bd9Sstevel@tonic-gate	call	panic
9127c478bd9Sstevel@tonic-gate1:
9137c478bd9Sstevel@tonic-gate#endif
9147c478bd9Sstevel@tonic-gatedo_copy:
9157c478bd9Sstevel@tonic-gate	movl	%esi, %eax		/* save registers */
9167c478bd9Sstevel@tonic-gate	movl	%edi, %edx
9177c478bd9Sstevel@tonic-gate	movl	ARG_COUNT(%esp), %ecx
9187c478bd9Sstevel@tonic-gate	movl	ARG_FROM(%esp), %esi
9197c478bd9Sstevel@tonic-gate	movl	ARG_TO(%esp), %edi
9207c478bd9Sstevel@tonic-gate
9217c478bd9Sstevel@tonic-gate	shrl	$2, %ecx		/* word count */
9227c478bd9Sstevel@tonic-gate	rep
9237c478bd9Sstevel@tonic-gate	  smovl
9247c478bd9Sstevel@tonic-gate	movl	ARG_COUNT(%esp), %ecx
9257c478bd9Sstevel@tonic-gate	andl	$3, %ecx		/* bytes left over */
9267c478bd9Sstevel@tonic-gate	rep
9277c478bd9Sstevel@tonic-gate	  smovb
9287c478bd9Sstevel@tonic-gate	movl	%eax, %esi		/* restore registers */
9297c478bd9Sstevel@tonic-gate	movl	%edx, %edi
9307c478bd9Sstevel@tonic-gate	ret
9317c478bd9Sstevel@tonic-gate	SET_SIZE(bcopy)
9327c478bd9Sstevel@tonic-gate
9337c478bd9Sstevel@tonic-gate#undef	ARG_COUNT
9347c478bd9Sstevel@tonic-gate#undef	ARG_FROM
9357c478bd9Sstevel@tonic-gate#undef	ARG_TO
9367c478bd9Sstevel@tonic-gate
9377c478bd9Sstevel@tonic-gate#endif	/* __i386 */
9387c478bd9Sstevel@tonic-gate#endif	/* __lint */
9397c478bd9Sstevel@tonic-gate
9407c478bd9Sstevel@tonic-gate
9417c478bd9Sstevel@tonic-gate/*
9427c478bd9Sstevel@tonic-gate * Zero a block of storage, returning an error code if we
9437c478bd9Sstevel@tonic-gate * take a kernel pagefault which cannot be resolved.
9447c478bd9Sstevel@tonic-gate * Returns errno value on pagefault error, 0 if all ok
9457c478bd9Sstevel@tonic-gate */
9467c478bd9Sstevel@tonic-gate
9477c478bd9Sstevel@tonic-gate#if defined(__lint)
9487c478bd9Sstevel@tonic-gate
9497c478bd9Sstevel@tonic-gate/* ARGSUSED */
9507c478bd9Sstevel@tonic-gateint
9517c478bd9Sstevel@tonic-gatekzero(void *addr, size_t count)
9527c478bd9Sstevel@tonic-gate{ return (0); }
9537c478bd9Sstevel@tonic-gate
9547c478bd9Sstevel@tonic-gate#else	/* __lint */
9557c478bd9Sstevel@tonic-gate
9567c478bd9Sstevel@tonic-gate#if defined(__amd64)
9577c478bd9Sstevel@tonic-gate
9587c478bd9Sstevel@tonic-gate	ENTRY(kzero)
9597c478bd9Sstevel@tonic-gate#ifdef DEBUG
960ae115bc7Smrj        cmpq	postbootkernelbase(%rip), %rdi	/* %rdi = addr */
9617c478bd9Sstevel@tonic-gate        jnb	0f
9627c478bd9Sstevel@tonic-gate        leaq	.kzero_panic_msg(%rip), %rdi
9637c478bd9Sstevel@tonic-gate	jmp	call_panic		/* setup stack and call panic */
9647c478bd9Sstevel@tonic-gate0:
9657c478bd9Sstevel@tonic-gate#endif
9667c478bd9Sstevel@tonic-gate	/*
967b08adf18SBill Holler	 * pass lofault value as 3rd argument for fault return
9687c478bd9Sstevel@tonic-gate	 */
9697c478bd9Sstevel@tonic-gate	leaq	_kzeroerr(%rip), %rdx
9707c478bd9Sstevel@tonic-gate
9717c478bd9Sstevel@tonic-gate	movq	%gs:CPU_THREAD, %r9	/* %r9 = thread addr */
9727c478bd9Sstevel@tonic-gate	movq	T_LOFAULT(%r9), %r11	/* save the current lofault */
9737c478bd9Sstevel@tonic-gate	movq	%rdx, T_LOFAULT(%r9)	/* new lofault */
97422cc0e45SBill Holler	call	bzero_altentry
975b08adf18SBill Holler	xorl	%eax, %eax
976b08adf18SBill Holler	movq	%r11, T_LOFAULT(%r9)	/* restore the original lofault */
977b08adf18SBill Holler	ret
9787c478bd9Sstevel@tonic-gate	/*
979b08adf18SBill Holler	 * A fault during bzero is indicated through an errno value
9807c478bd9Sstevel@tonic-gate	 * in %rax when we iretq to here.
9817c478bd9Sstevel@tonic-gate	 */
9827c478bd9Sstevel@tonic-gate_kzeroerr:
983b08adf18SBill Holler	addq	$8, %rsp		/* pop bzero_altentry call ret addr */
9847c478bd9Sstevel@tonic-gate	movq	%r11, T_LOFAULT(%r9)	/* restore the original lofault */
9857c478bd9Sstevel@tonic-gate	ret
9867c478bd9Sstevel@tonic-gate	SET_SIZE(kzero)
9877c478bd9Sstevel@tonic-gate
9887c478bd9Sstevel@tonic-gate#elif defined(__i386)
9897c478bd9Sstevel@tonic-gate
9907c478bd9Sstevel@tonic-gate#define	ARG_ADDR	8
9917c478bd9Sstevel@tonic-gate#define	ARG_COUNT	12
9927c478bd9Sstevel@tonic-gate
9937c478bd9Sstevel@tonic-gate	ENTRY(kzero)
9947c478bd9Sstevel@tonic-gate#ifdef DEBUG
9957c478bd9Sstevel@tonic-gate	pushl	%ebp
9967c478bd9Sstevel@tonic-gate	movl	%esp, %ebp
997ae115bc7Smrj	movl	postbootkernelbase, %eax
9987c478bd9Sstevel@tonic-gate        cmpl	%eax, ARG_ADDR(%ebp)
9997c478bd9Sstevel@tonic-gate        jnb	0f
10007c478bd9Sstevel@tonic-gate        pushl   $.kzero_panic_msg
10017c478bd9Sstevel@tonic-gate        call    panic
10027c478bd9Sstevel@tonic-gate0:	popl	%ebp
10037c478bd9Sstevel@tonic-gate#endif
10047c478bd9Sstevel@tonic-gate	lea	_kzeroerr, %eax		/* kzeroerr is lofault value */
10057c478bd9Sstevel@tonic-gate
10067c478bd9Sstevel@tonic-gate	pushl	%ebp			/* save stack base */
10077c478bd9Sstevel@tonic-gate	movl	%esp, %ebp		/* set new stack base */
10087c478bd9Sstevel@tonic-gate	pushl	%edi			/* save %edi */
10097c478bd9Sstevel@tonic-gate
10107c478bd9Sstevel@tonic-gate	mov	%gs:CPU_THREAD, %edx
10117c478bd9Sstevel@tonic-gate	movl	T_LOFAULT(%edx), %edi
10127c478bd9Sstevel@tonic-gate	pushl	%edi			/* save the current lofault */
10137c478bd9Sstevel@tonic-gate	movl	%eax, T_LOFAULT(%edx)	/* new lofault */
10147c478bd9Sstevel@tonic-gate
10157c478bd9Sstevel@tonic-gate	movl	ARG_COUNT(%ebp), %ecx	/* get size in bytes */
10167c478bd9Sstevel@tonic-gate	movl	ARG_ADDR(%ebp), %edi	/* %edi <- address of bytes to clear */
10177c478bd9Sstevel@tonic-gate	shrl	$2, %ecx		/* Count of double words to zero */
10187c478bd9Sstevel@tonic-gate	xorl	%eax, %eax		/* sstol val */
10197c478bd9Sstevel@tonic-gate	rep
10207c478bd9Sstevel@tonic-gate	  sstol			/* %ecx contains words to clear (%eax=0) */
10217c478bd9Sstevel@tonic-gate
10227c478bd9Sstevel@tonic-gate	movl	ARG_COUNT(%ebp), %ecx	/* get size in bytes */
10237c478bd9Sstevel@tonic-gate	andl	$3, %ecx		/* do mod 4 */
10247c478bd9Sstevel@tonic-gate	rep
10257c478bd9Sstevel@tonic-gate	  sstob			/* %ecx contains residual bytes to clear */
10267c478bd9Sstevel@tonic-gate
10277c478bd9Sstevel@tonic-gate	/*
1028b08adf18SBill Holler	 * A fault during kzero is indicated through an errno value
10297c478bd9Sstevel@tonic-gate	 * in %eax when we iret to here.
10307c478bd9Sstevel@tonic-gate	 */
10317c478bd9Sstevel@tonic-gate_kzeroerr:
10327c478bd9Sstevel@tonic-gate	popl	%edi
10337c478bd9Sstevel@tonic-gate	movl	%edi, T_LOFAULT(%edx)	/* restore the original lofault */
10347c478bd9Sstevel@tonic-gate	popl	%edi
10357c478bd9Sstevel@tonic-gate	popl	%ebp
10367c478bd9Sstevel@tonic-gate	ret
10377c478bd9Sstevel@tonic-gate	SET_SIZE(kzero)
10387c478bd9Sstevel@tonic-gate
10397c478bd9Sstevel@tonic-gate#undef	ARG_ADDR
10407c478bd9Sstevel@tonic-gate#undef	ARG_COUNT
10417c478bd9Sstevel@tonic-gate
10427c478bd9Sstevel@tonic-gate#endif	/* __i386 */
10437c478bd9Sstevel@tonic-gate#endif	/* __lint */
10447c478bd9Sstevel@tonic-gate
10457c478bd9Sstevel@tonic-gate/*
10467c478bd9Sstevel@tonic-gate * Zero a block of storage.
10477c478bd9Sstevel@tonic-gate */
10487c478bd9Sstevel@tonic-gate
10497c478bd9Sstevel@tonic-gate#if defined(__lint)
10507c478bd9Sstevel@tonic-gate
10517c478bd9Sstevel@tonic-gate/* ARGSUSED */
10527c478bd9Sstevel@tonic-gatevoid
10537c478bd9Sstevel@tonic-gatebzero(void *addr, size_t count)
10547c478bd9Sstevel@tonic-gate{}
10557c478bd9Sstevel@tonic-gate
10567c478bd9Sstevel@tonic-gate#else	/* __lint */
10577c478bd9Sstevel@tonic-gate
10587c478bd9Sstevel@tonic-gate#if defined(__amd64)
10597c478bd9Sstevel@tonic-gate
10607c478bd9Sstevel@tonic-gate	ENTRY(bzero)
10617c478bd9Sstevel@tonic-gate#ifdef DEBUG
1062ae115bc7Smrj	cmpq	postbootkernelbase(%rip), %rdi	/* %rdi = addr */
10637c478bd9Sstevel@tonic-gate	jnb	0f
10647c478bd9Sstevel@tonic-gate	leaq	.bzero_panic_msg(%rip), %rdi
10657c478bd9Sstevel@tonic-gate	jmp	call_panic		/* setup stack and call panic */
10667c478bd9Sstevel@tonic-gate0:
10677c478bd9Sstevel@tonic-gate#endif
106822cc0e45SBill Holler	ALTENTRY(bzero_altentry)
10697c478bd9Sstevel@tonic-gatedo_zero:
107022cc0e45SBill Holler#define	L(s) .bzero/**/s
107122cc0e45SBill Holler	xorl	%eax, %eax
107222cc0e45SBill Holler
107322cc0e45SBill Holler	cmpq	$0x50, %rsi		/* 80 */
1074*9b6707c5SRobert Mustacchi	jae	L(ck_align)
107522cc0e45SBill Holler
107622cc0e45SBill Holler	/*
107722cc0e45SBill Holler	 * Performance data shows many caller's are zeroing small buffers. So
107822cc0e45SBill Holler	 * for best perf for these sizes unrolled code is used. Store zeros
107922cc0e45SBill Holler	 * without worrying about alignment.
108022cc0e45SBill Holler	 */
108122cc0e45SBill Holler	leaq	L(setPxQx)(%rip), %r10
108222cc0e45SBill Holler	addq	%rsi, %rdi
108322cc0e45SBill Holler	movslq	(%r10,%rsi,4), %rcx
108422cc0e45SBill Holler	leaq	(%rcx,%r10,1), %r10
108522cc0e45SBill Holler	jmpq	*%r10
108622cc0e45SBill Holler
108722cc0e45SBill Holler	.p2align 4
108822cc0e45SBill HollerL(setPxQx):
108922cc0e45SBill Holler	.int       L(P0Q0)-L(setPxQx)	/* 0 */
109022cc0e45SBill Holler	.int       L(P1Q0)-L(setPxQx)
109122cc0e45SBill Holler	.int       L(P2Q0)-L(setPxQx)
109222cc0e45SBill Holler	.int       L(P3Q0)-L(setPxQx)
109322cc0e45SBill Holler	.int       L(P4Q0)-L(setPxQx)
109422cc0e45SBill Holler	.int       L(P5Q0)-L(setPxQx)
109522cc0e45SBill Holler	.int       L(P6Q0)-L(setPxQx)
109622cc0e45SBill Holler	.int       L(P7Q0)-L(setPxQx)
109722cc0e45SBill Holler
109822cc0e45SBill Holler	.int       L(P0Q1)-L(setPxQx)	/* 8 */
109922cc0e45SBill Holler	.int       L(P1Q1)-L(setPxQx)
110022cc0e45SBill Holler	.int       L(P2Q1)-L(setPxQx)
110122cc0e45SBill Holler	.int       L(P3Q1)-L(setPxQx)
110222cc0e45SBill Holler	.int       L(P4Q1)-L(setPxQx)
110322cc0e45SBill Holler	.int       L(P5Q1)-L(setPxQx)
110422cc0e45SBill Holler	.int       L(P6Q1)-L(setPxQx)
110522cc0e45SBill Holler	.int       L(P7Q1)-L(setPxQx)
110622cc0e45SBill Holler
110722cc0e45SBill Holler	.int       L(P0Q2)-L(setPxQx)	/* 16 */
110822cc0e45SBill Holler	.int       L(P1Q2)-L(setPxQx)
110922cc0e45SBill Holler	.int       L(P2Q2)-L(setPxQx)
111022cc0e45SBill Holler	.int       L(P3Q2)-L(setPxQx)
111122cc0e45SBill Holler	.int       L(P4Q2)-L(setPxQx)
111222cc0e45SBill Holler	.int       L(P5Q2)-L(setPxQx)
111322cc0e45SBill Holler	.int       L(P6Q2)-L(setPxQx)
111422cc0e45SBill Holler	.int       L(P7Q2)-L(setPxQx)
111522cc0e45SBill Holler
111622cc0e45SBill Holler	.int       L(P0Q3)-L(setPxQx)	/* 24 */
111722cc0e45SBill Holler	.int       L(P1Q3)-L(setPxQx)
111822cc0e45SBill Holler	.int       L(P2Q3)-L(setPxQx)
111922cc0e45SBill Holler	.int       L(P3Q3)-L(setPxQx)
112022cc0e45SBill Holler	.int       L(P4Q3)-L(setPxQx)
112122cc0e45SBill Holler	.int       L(P5Q3)-L(setPxQx)
112222cc0e45SBill Holler	.int       L(P6Q3)-L(setPxQx)
112322cc0e45SBill Holler	.int       L(P7Q3)-L(setPxQx)
112422cc0e45SBill Holler
112522cc0e45SBill Holler	.int       L(P0Q4)-L(setPxQx)	/* 32 */
112622cc0e45SBill Holler	.int       L(P1Q4)-L(setPxQx)
112722cc0e45SBill Holler	.int       L(P2Q4)-L(setPxQx)
112822cc0e45SBill Holler	.int       L(P3Q4)-L(setPxQx)
112922cc0e45SBill Holler	.int       L(P4Q4)-L(setPxQx)
113022cc0e45SBill Holler	.int       L(P5Q4)-L(setPxQx)
113122cc0e45SBill Holler	.int       L(P6Q4)-L(setPxQx)
113222cc0e45SBill Holler	.int       L(P7Q4)-L(setPxQx)
113322cc0e45SBill Holler
113422cc0e45SBill Holler	.int       L(P0Q5)-L(setPxQx)	/* 40 */
113522cc0e45SBill Holler	.int       L(P1Q5)-L(setPxQx)
113622cc0e45SBill Holler	.int       L(P2Q5)-L(setPxQx)
113722cc0e45SBill Holler	.int       L(P3Q5)-L(setPxQx)
113822cc0e45SBill Holler	.int       L(P4Q5)-L(setPxQx)
113922cc0e45SBill Holler	.int       L(P5Q5)-L(setPxQx)
114022cc0e45SBill Holler	.int       L(P6Q5)-L(setPxQx)
114122cc0e45SBill Holler	.int       L(P7Q5)-L(setPxQx)
114222cc0e45SBill Holler
114322cc0e45SBill Holler	.int       L(P0Q6)-L(setPxQx)	/* 48 */
114422cc0e45SBill Holler	.int       L(P1Q6)-L(setPxQx)
114522cc0e45SBill Holler	.int       L(P2Q6)-L(setPxQx)
114622cc0e45SBill Holler	.int       L(P3Q6)-L(setPxQx)
114722cc0e45SBill Holler	.int       L(P4Q6)-L(setPxQx)
114822cc0e45SBill Holler	.int       L(P5Q6)-L(setPxQx)
114922cc0e45SBill Holler	.int       L(P6Q6)-L(setPxQx)
115022cc0e45SBill Holler	.int       L(P7Q6)-L(setPxQx)
115122cc0e45SBill Holler
115222cc0e45SBill Holler	.int       L(P0Q7)-L(setPxQx)	/* 56 */
115322cc0e45SBill Holler	.int       L(P1Q7)-L(setPxQx)
115422cc0e45SBill Holler	.int       L(P2Q7)-L(setPxQx)
115522cc0e45SBill Holler	.int       L(P3Q7)-L(setPxQx)
115622cc0e45SBill Holler	.int       L(P4Q7)-L(setPxQx)
115722cc0e45SBill Holler	.int       L(P5Q7)-L(setPxQx)
115822cc0e45SBill Holler	.int       L(P6Q7)-L(setPxQx)
115922cc0e45SBill Holler	.int       L(P7Q7)-L(setPxQx)
116022cc0e45SBill Holler
116122cc0e45SBill Holler	.int       L(P0Q8)-L(setPxQx)	/* 64 */
116222cc0e45SBill Holler	.int       L(P1Q8)-L(setPxQx)
116322cc0e45SBill Holler	.int       L(P2Q8)-L(setPxQx)
116422cc0e45SBill Holler	.int       L(P3Q8)-L(setPxQx)
116522cc0e45SBill Holler	.int       L(P4Q8)-L(setPxQx)
116622cc0e45SBill Holler	.int       L(P5Q8)-L(setPxQx)
116722cc0e45SBill Holler	.int       L(P6Q8)-L(setPxQx)
116822cc0e45SBill Holler	.int       L(P7Q8)-L(setPxQx)
116922cc0e45SBill Holler
117022cc0e45SBill Holler	.int       L(P0Q9)-L(setPxQx)	/* 72 */
117122cc0e45SBill Holler	.int       L(P1Q9)-L(setPxQx)
117222cc0e45SBill Holler	.int       L(P2Q9)-L(setPxQx)
117322cc0e45SBill Holler	.int       L(P3Q9)-L(setPxQx)
117422cc0e45SBill Holler	.int       L(P4Q9)-L(setPxQx)
117522cc0e45SBill Holler	.int       L(P5Q9)-L(setPxQx)
117622cc0e45SBill Holler	.int       L(P6Q9)-L(setPxQx)
117722cc0e45SBill Holler	.int       L(P7Q9)-L(setPxQx)	/* 79 */
117822cc0e45SBill Holler
117922cc0e45SBill Holler	.p2align 4
118022cc0e45SBill HollerL(P0Q9): mov    %rax, -0x48(%rdi)
118122cc0e45SBill HollerL(P0Q8): mov    %rax, -0x40(%rdi)
118222cc0e45SBill HollerL(P0Q7): mov    %rax, -0x38(%rdi)
118322cc0e45SBill HollerL(P0Q6): mov    %rax, -0x30(%rdi)
118422cc0e45SBill HollerL(P0Q5): mov    %rax, -0x28(%rdi)
118522cc0e45SBill HollerL(P0Q4): mov    %rax, -0x20(%rdi)
118622cc0e45SBill HollerL(P0Q3): mov    %rax, -0x18(%rdi)
118722cc0e45SBill HollerL(P0Q2): mov    %rax, -0x10(%rdi)
118822cc0e45SBill HollerL(P0Q1): mov    %rax, -0x8(%rdi)
118922cc0e45SBill HollerL(P0Q0):
119022cc0e45SBill Holler	 ret
119122cc0e45SBill Holler
119222cc0e45SBill Holler	.p2align 4
119322cc0e45SBill HollerL(P1Q9): mov    %rax, -0x49(%rdi)
119422cc0e45SBill HollerL(P1Q8): mov    %rax, -0x41(%rdi)
119522cc0e45SBill HollerL(P1Q7): mov    %rax, -0x39(%rdi)
119622cc0e45SBill HollerL(P1Q6): mov    %rax, -0x31(%rdi)
119722cc0e45SBill HollerL(P1Q5): mov    %rax, -0x29(%rdi)
119822cc0e45SBill HollerL(P1Q4): mov    %rax, -0x21(%rdi)
119922cc0e45SBill HollerL(P1Q3): mov    %rax, -0x19(%rdi)
120022cc0e45SBill HollerL(P1Q2): mov    %rax, -0x11(%rdi)
120122cc0e45SBill HollerL(P1Q1): mov    %rax, -0x9(%rdi)
120222cc0e45SBill HollerL(P1Q0): mov    %al, -0x1(%rdi)
120322cc0e45SBill Holler	 ret
120422cc0e45SBill Holler
120522cc0e45SBill Holler	.p2align 4
120622cc0e45SBill HollerL(P2Q9): mov    %rax, -0x4a(%rdi)
120722cc0e45SBill HollerL(P2Q8): mov    %rax, -0x42(%rdi)
120822cc0e45SBill HollerL(P2Q7): mov    %rax, -0x3a(%rdi)
120922cc0e45SBill HollerL(P2Q6): mov    %rax, -0x32(%rdi)
121022cc0e45SBill HollerL(P2Q5): mov    %rax, -0x2a(%rdi)
121122cc0e45SBill HollerL(P2Q4): mov    %rax, -0x22(%rdi)
121222cc0e45SBill HollerL(P2Q3): mov    %rax, -0x1a(%rdi)
121322cc0e45SBill HollerL(P2Q2): mov    %rax, -0x12(%rdi)
121422cc0e45SBill HollerL(P2Q1): mov    %rax, -0xa(%rdi)
121522cc0e45SBill HollerL(P2Q0): mov    %ax, -0x2(%rdi)
121622cc0e45SBill Holler	 ret
121722cc0e45SBill Holler
121822cc0e45SBill Holler	.p2align 4
121922cc0e45SBill HollerL(P3Q9): mov    %rax, -0x4b(%rdi)
122022cc0e45SBill HollerL(P3Q8): mov    %rax, -0x43(%rdi)
122122cc0e45SBill HollerL(P3Q7): mov    %rax, -0x3b(%rdi)
122222cc0e45SBill HollerL(P3Q6): mov    %rax, -0x33(%rdi)
122322cc0e45SBill HollerL(P3Q5): mov    %rax, -0x2b(%rdi)
122422cc0e45SBill HollerL(P3Q4): mov    %rax, -0x23(%rdi)
122522cc0e45SBill HollerL(P3Q3): mov    %rax, -0x1b(%rdi)
122622cc0e45SBill HollerL(P3Q2): mov    %rax, -0x13(%rdi)
122722cc0e45SBill HollerL(P3Q1): mov    %rax, -0xb(%rdi)
122822cc0e45SBill HollerL(P3Q0): mov    %ax, -0x3(%rdi)
122922cc0e45SBill Holler	 mov    %al, -0x1(%rdi)
123022cc0e45SBill Holler	 ret
123122cc0e45SBill Holler
123222cc0e45SBill Holler	.p2align 4
123322cc0e45SBill HollerL(P4Q9): mov    %rax, -0x4c(%rdi)
123422cc0e45SBill HollerL(P4Q8): mov    %rax, -0x44(%rdi)
123522cc0e45SBill HollerL(P4Q7): mov    %rax, -0x3c(%rdi)
123622cc0e45SBill HollerL(P4Q6): mov    %rax, -0x34(%rdi)
123722cc0e45SBill HollerL(P4Q5): mov    %rax, -0x2c(%rdi)
123822cc0e45SBill HollerL(P4Q4): mov    %rax, -0x24(%rdi)
123922cc0e45SBill HollerL(P4Q3): mov    %rax, -0x1c(%rdi)
124022cc0e45SBill HollerL(P4Q2): mov    %rax, -0x14(%rdi)
124122cc0e45SBill HollerL(P4Q1): mov    %rax, -0xc(%rdi)
124222cc0e45SBill HollerL(P4Q0): mov    %eax, -0x4(%rdi)
124322cc0e45SBill Holler	 ret
124422cc0e45SBill Holler
124522cc0e45SBill Holler	.p2align 4
124622cc0e45SBill HollerL(P5Q9): mov    %rax, -0x4d(%rdi)
124722cc0e45SBill HollerL(P5Q8): mov    %rax, -0x45(%rdi)
124822cc0e45SBill HollerL(P5Q7): mov    %rax, -0x3d(%rdi)
124922cc0e45SBill HollerL(P5Q6): mov    %rax, -0x35(%rdi)
125022cc0e45SBill HollerL(P5Q5): mov    %rax, -0x2d(%rdi)
125122cc0e45SBill HollerL(P5Q4): mov    %rax, -0x25(%rdi)
125222cc0e45SBill HollerL(P5Q3): mov    %rax, -0x1d(%rdi)
125322cc0e45SBill HollerL(P5Q2): mov    %rax, -0x15(%rdi)
125422cc0e45SBill HollerL(P5Q1): mov    %rax, -0xd(%rdi)
125522cc0e45SBill HollerL(P5Q0): mov    %eax, -0x5(%rdi)
125622cc0e45SBill Holler	 mov    %al, -0x1(%rdi)
125722cc0e45SBill Holler	 ret
125822cc0e45SBill Holler
125922cc0e45SBill Holler	.p2align 4
126022cc0e45SBill HollerL(P6Q9): mov    %rax, -0x4e(%rdi)
126122cc0e45SBill HollerL(P6Q8): mov    %rax, -0x46(%rdi)
126222cc0e45SBill HollerL(P6Q7): mov    %rax, -0x3e(%rdi)
126322cc0e45SBill HollerL(P6Q6): mov    %rax, -0x36(%rdi)
126422cc0e45SBill HollerL(P6Q5): mov    %rax, -0x2e(%rdi)
126522cc0e45SBill HollerL(P6Q4): mov    %rax, -0x26(%rdi)
126622cc0e45SBill HollerL(P6Q3): mov    %rax, -0x1e(%rdi)
126722cc0e45SBill HollerL(P6Q2): mov    %rax, -0x16(%rdi)
126822cc0e45SBill HollerL(P6Q1): mov    %rax, -0xe(%rdi)
126922cc0e45SBill HollerL(P6Q0): mov    %eax, -0x6(%rdi)
127022cc0e45SBill Holler	 mov    %ax, -0x2(%rdi)
127122cc0e45SBill Holler	 ret
127222cc0e45SBill Holler
127322cc0e45SBill Holler	.p2align 4
127422cc0e45SBill HollerL(P7Q9): mov    %rax, -0x4f(%rdi)
127522cc0e45SBill HollerL(P7Q8): mov    %rax, -0x47(%rdi)
127622cc0e45SBill HollerL(P7Q7): mov    %rax, -0x3f(%rdi)
127722cc0e45SBill HollerL(P7Q6): mov    %rax, -0x37(%rdi)
127822cc0e45SBill HollerL(P7Q5): mov    %rax, -0x2f(%rdi)
127922cc0e45SBill HollerL(P7Q4): mov    %rax, -0x27(%rdi)
128022cc0e45SBill HollerL(P7Q3): mov    %rax, -0x1f(%rdi)
128122cc0e45SBill HollerL(P7Q2): mov    %rax, -0x17(%rdi)
128222cc0e45SBill HollerL(P7Q1): mov    %rax, -0xf(%rdi)
128322cc0e45SBill HollerL(P7Q0): mov    %eax, -0x7(%rdi)
128422cc0e45SBill Holler	 mov    %ax, -0x3(%rdi)
128522cc0e45SBill Holler	 mov    %al, -0x1(%rdi)
128622cc0e45SBill Holler	 ret
128722cc0e45SBill Holler
128822cc0e45SBill Holler	/*
128922cc0e45SBill Holler	 * Align to a 16-byte boundary. Avoids penalties from unaligned stores
129022cc0e45SBill Holler	 * as well as from stores spanning cachelines. Note 16-byte alignment
129122cc0e45SBill Holler	 * is better in case where rep sstosq is used.
129222cc0e45SBill Holler	 */
129322cc0e45SBill Holler	.p2align 4
129422cc0e45SBill HollerL(ck_align):
129522cc0e45SBill Holler	test	$0xf, %rdi
129622cc0e45SBill Holler	jz	L(aligned_now)
129722cc0e45SBill Holler	test	$1, %rdi
129822cc0e45SBill Holler	jz	2f
129922cc0e45SBill Holler	mov	%al, (%rdi)
130022cc0e45SBill Holler	dec	%rsi
130122cc0e45SBill Holler	lea	1(%rdi),%rdi
130222cc0e45SBill Holler2:
130322cc0e45SBill Holler	test	$2, %rdi
130422cc0e45SBill Holler	jz	4f
130522cc0e45SBill Holler	mov	%ax, (%rdi)
130622cc0e45SBill Holler	sub	$2, %rsi
130722cc0e45SBill Holler	lea	2(%rdi),%rdi
130822cc0e45SBill Holler4:
130922cc0e45SBill Holler	test	$4, %rdi
131022cc0e45SBill Holler	jz	8f
131122cc0e45SBill Holler	mov	%eax, (%rdi)
131222cc0e45SBill Holler	sub	$4, %rsi
131322cc0e45SBill Holler	lea	4(%rdi),%rdi
131422cc0e45SBill Holler8:
131522cc0e45SBill Holler	test	$8, %rdi
131622cc0e45SBill Holler	jz	L(aligned_now)
131722cc0e45SBill Holler	mov	%rax, (%rdi)
131822cc0e45SBill Holler	sub	$8, %rsi
131922cc0e45SBill Holler	lea	8(%rdi),%rdi
132022cc0e45SBill Holler
132122cc0e45SBill Holler	/*
132222cc0e45SBill Holler	 * For large sizes rep sstoq is fastest.
132322cc0e45SBill Holler	 * Transition point determined experimentally as measured on
132422cc0e45SBill Holler	 * Intel Xeon processors (incl. Nehalem) and AMD Opteron.
132522cc0e45SBill Holler	 */
132622cc0e45SBill HollerL(aligned_now):
132722cc0e45SBill Holler	cmp	$BZERO_USE_REP, %rsi
1328*9b6707c5SRobert Mustacchi	ja	L(use_rep)
132922cc0e45SBill Holler
133022cc0e45SBill Holler	/*
133122cc0e45SBill Holler	 * zero 64-bytes per loop
133222cc0e45SBill Holler	 */
133322cc0e45SBill Holler	.p2align 4
133422cc0e45SBill HollerL(bzero_loop):
133522cc0e45SBill Holler	leaq	-0x40(%rsi), %rsi
133622cc0e45SBill Holler	cmpq	$0x40, %rsi
133722cc0e45SBill Holler	movq	%rax, (%rdi)
133822cc0e45SBill Holler	movq	%rax, 0x8(%rdi)
133922cc0e45SBill Holler	movq	%rax, 0x10(%rdi)
134022cc0e45SBill Holler	movq	%rax, 0x18(%rdi)
134122cc0e45SBill Holler	movq	%rax, 0x20(%rdi)
134222cc0e45SBill Holler	movq	%rax, 0x28(%rdi)
134322cc0e45SBill Holler	movq	%rax, 0x30(%rdi)
134422cc0e45SBill Holler	movq	%rax, 0x38(%rdi)
134522cc0e45SBill Holler	leaq	0x40(%rdi), %rdi
1346*9b6707c5SRobert Mustacchi	jae	L(bzero_loop)
134722cc0e45SBill Holler
134822cc0e45SBill Holler	/*
134922cc0e45SBill Holler	 * Clear any remaining bytes..
135022cc0e45SBill Holler	 */
135122cc0e45SBill Holler9:
135222cc0e45SBill Holler	leaq	L(setPxQx)(%rip), %r10
135322cc0e45SBill Holler	addq	%rsi, %rdi
135422cc0e45SBill Holler	movslq	(%r10,%rsi,4), %rcx
135522cc0e45SBill Holler	leaq	(%rcx,%r10,1), %r10
135622cc0e45SBill Holler	jmpq	*%r10
135722cc0e45SBill Holler
135822cc0e45SBill Holler	/*
135922cc0e45SBill Holler	 * Use rep sstoq. Clear any remainder via unrolled code
136022cc0e45SBill Holler	 */
136122cc0e45SBill Holler	.p2align 4
136222cc0e45SBill HollerL(use_rep):
13637c478bd9Sstevel@tonic-gate	movq	%rsi, %rcx		/* get size in bytes */
13647c478bd9Sstevel@tonic-gate	shrq	$3, %rcx		/* count of 8-byte words to zero */
13657c478bd9Sstevel@tonic-gate	rep
13667c478bd9Sstevel@tonic-gate	  sstoq				/* %rcx = words to clear (%rax=0) */
136722cc0e45SBill Holler	andq	$7, %rsi		/* remaining bytes */
136822cc0e45SBill Holler	jnz	9b
13697c478bd9Sstevel@tonic-gate	ret
137022cc0e45SBill Holler#undef	L
137122cc0e45SBill Holler	SET_SIZE(bzero_altentry)
13727c478bd9Sstevel@tonic-gate	SET_SIZE(bzero)
13737c478bd9Sstevel@tonic-gate
13747c478bd9Sstevel@tonic-gate#elif defined(__i386)
13757c478bd9Sstevel@tonic-gate
13767c478bd9Sstevel@tonic-gate#define	ARG_ADDR	4
13777c478bd9Sstevel@tonic-gate#define	ARG_COUNT	8
13787c478bd9Sstevel@tonic-gate
13797c478bd9Sstevel@tonic-gate	ENTRY(bzero)
13807c478bd9Sstevel@tonic-gate#ifdef DEBUG
1381ae115bc7Smrj	movl	postbootkernelbase, %eax
13827c478bd9Sstevel@tonic-gate	cmpl	%eax, ARG_ADDR(%esp)
13837c478bd9Sstevel@tonic-gate	jnb	0f
13847c478bd9Sstevel@tonic-gate	pushl	%ebp
13857c478bd9Sstevel@tonic-gate	movl	%esp, %ebp
13867c478bd9Sstevel@tonic-gate	pushl	$.bzero_panic_msg
13877c478bd9Sstevel@tonic-gate	call	panic
13887c478bd9Sstevel@tonic-gate0:
13897c478bd9Sstevel@tonic-gate#endif
13907c478bd9Sstevel@tonic-gatedo_zero:
13917c478bd9Sstevel@tonic-gate	movl	%edi, %edx
13927c478bd9Sstevel@tonic-gate	movl	ARG_COUNT(%esp), %ecx
13937c478bd9Sstevel@tonic-gate	movl	ARG_ADDR(%esp), %edi
13947c478bd9Sstevel@tonic-gate	shrl	$2, %ecx
13957c478bd9Sstevel@tonic-gate	xorl	%eax, %eax
13967c478bd9Sstevel@tonic-gate	rep
13977c478bd9Sstevel@tonic-gate	  sstol
13987c478bd9Sstevel@tonic-gate	movl	ARG_COUNT(%esp), %ecx
13997c478bd9Sstevel@tonic-gate	andl	$3, %ecx
14007c478bd9Sstevel@tonic-gate	rep
14017c478bd9Sstevel@tonic-gate	  sstob
14027c478bd9Sstevel@tonic-gate	movl	%edx, %edi
14037c478bd9Sstevel@tonic-gate	ret
14047c478bd9Sstevel@tonic-gate	SET_SIZE(bzero)
14057c478bd9Sstevel@tonic-gate
14067c478bd9Sstevel@tonic-gate#undef	ARG_ADDR
14077c478bd9Sstevel@tonic-gate#undef	ARG_COUNT
14087c478bd9Sstevel@tonic-gate
14097c478bd9Sstevel@tonic-gate#endif	/* __i386 */
14107c478bd9Sstevel@tonic-gate#endif	/* __lint */
14117c478bd9Sstevel@tonic-gate
14127c478bd9Sstevel@tonic-gate/*
14137c478bd9Sstevel@tonic-gate * Transfer data to and from user space -
14147c478bd9Sstevel@tonic-gate * Note that these routines can cause faults
14157c478bd9Sstevel@tonic-gate * It is assumed that the kernel has nothing at
14167c478bd9Sstevel@tonic-gate * less than KERNELBASE in the virtual address space.
14177c478bd9Sstevel@tonic-gate *
14187c478bd9Sstevel@tonic-gate * Note that copyin(9F) and copyout(9F) are part of the
14197c478bd9Sstevel@tonic-gate * DDI/DKI which specifies that they return '-1' on "errors."
14207c478bd9Sstevel@tonic-gate *
14217c478bd9Sstevel@tonic-gate * Sigh.
14227c478bd9Sstevel@tonic-gate *
14237c478bd9Sstevel@tonic-gate * So there's two extremely similar routines - xcopyin_nta() and
14247c478bd9Sstevel@tonic-gate * xcopyout_nta() which return the errno that we've faithfully computed.
14257c478bd9Sstevel@tonic-gate * This allows other callers (e.g. uiomove(9F)) to work correctly.
14267c478bd9Sstevel@tonic-gate * Given that these are used pretty heavily, we expand the calling
14277c478bd9Sstevel@tonic-gate * sequences inline for all flavours (rather than making wrappers).
14287c478bd9Sstevel@tonic-gate */
14297c478bd9Sstevel@tonic-gate
14307c478bd9Sstevel@tonic-gate/*
14317c478bd9Sstevel@tonic-gate * Copy user data to kernel space.
14327c478bd9Sstevel@tonic-gate */
14337c478bd9Sstevel@tonic-gate
14347c478bd9Sstevel@tonic-gate#if defined(__lint)
14357c478bd9Sstevel@tonic-gate
14367c478bd9Sstevel@tonic-gate/* ARGSUSED */
14377c478bd9Sstevel@tonic-gateint
14387c478bd9Sstevel@tonic-gatecopyin(const void *uaddr, void *kaddr, size_t count)
14397c478bd9Sstevel@tonic-gate{ return (0); }
14407c478bd9Sstevel@tonic-gate
14417c478bd9Sstevel@tonic-gate#else	/* lint */
14427c478bd9Sstevel@tonic-gate
14437c478bd9Sstevel@tonic-gate#if defined(__amd64)
14447c478bd9Sstevel@tonic-gate
14457c478bd9Sstevel@tonic-gate	ENTRY(copyin)
14467c478bd9Sstevel@tonic-gate	pushq	%rbp
14477c478bd9Sstevel@tonic-gate	movq	%rsp, %rbp
1448b08adf18SBill Holler	subq	$24, %rsp
14497c478bd9Sstevel@tonic-gate
14507c478bd9Sstevel@tonic-gate	/*
14517c478bd9Sstevel@tonic-gate	 * save args in case we trap and need to rerun as a copyop
14527c478bd9Sstevel@tonic-gate	 */
14537c478bd9Sstevel@tonic-gate	movq	%rdi, (%rsp)
14547c478bd9Sstevel@tonic-gate	movq	%rsi, 0x8(%rsp)
14557c478bd9Sstevel@tonic-gate	movq	%rdx, 0x10(%rsp)
14567c478bd9Sstevel@tonic-gate
14577c478bd9Sstevel@tonic-gate	movq	kernelbase(%rip), %rax
14587c478bd9Sstevel@tonic-gate#ifdef DEBUG
14597c478bd9Sstevel@tonic-gate	cmpq	%rax, %rsi		/* %rsi = kaddr */
14607c478bd9Sstevel@tonic-gate	jnb	1f
14617c478bd9Sstevel@tonic-gate	leaq	.copyin_panic_msg(%rip), %rdi
14627c478bd9Sstevel@tonic-gate	xorl	%eax, %eax
14637c478bd9Sstevel@tonic-gate	call	panic
14647c478bd9Sstevel@tonic-gate1:
14657c478bd9Sstevel@tonic-gate#endif
14667c478bd9Sstevel@tonic-gate	/*
14677c478bd9Sstevel@tonic-gate	 * pass lofault value as 4th argument to do_copy_fault
14687c478bd9Sstevel@tonic-gate	 */
14697c478bd9Sstevel@tonic-gate	leaq	_copyin_err(%rip), %rcx
14707c478bd9Sstevel@tonic-gate
14717c478bd9Sstevel@tonic-gate	movq	%gs:CPU_THREAD, %r9
14727c478bd9Sstevel@tonic-gate	cmpq	%rax, %rdi		/* test uaddr < kernelbase */
14737c478bd9Sstevel@tonic-gate	jb	do_copy_fault
14747c478bd9Sstevel@tonic-gate	jmp	3f
14757c478bd9Sstevel@tonic-gate
14767c478bd9Sstevel@tonic-gate_copyin_err:
14777c478bd9Sstevel@tonic-gate	movq	%r11, T_LOFAULT(%r9)	/* restore original lofault */
1478b08adf18SBill Holler	addq	$8, %rsp		/* pop bcopy_altentry call ret addr */
14797c478bd9Sstevel@tonic-gate3:
14807c478bd9Sstevel@tonic-gate	movq	T_COPYOPS(%r9), %rax
14817c478bd9Sstevel@tonic-gate	cmpq	$0, %rax
14827c478bd9Sstevel@tonic-gate	jz	2f
14837c478bd9Sstevel@tonic-gate	/*
14847c478bd9Sstevel@tonic-gate	 * reload args for the copyop
14857c478bd9Sstevel@tonic-gate	 */
14867c478bd9Sstevel@tonic-gate	movq	(%rsp), %rdi
14877c478bd9Sstevel@tonic-gate	movq	0x8(%rsp), %rsi
14887c478bd9Sstevel@tonic-gate	movq	0x10(%rsp), %rdx
14897c478bd9Sstevel@tonic-gate	leave
14907c478bd9Sstevel@tonic-gate	jmp	*CP_COPYIN(%rax)
14917c478bd9Sstevel@tonic-gate
14927c478bd9Sstevel@tonic-gate2:	movl	$-1, %eax
14937c478bd9Sstevel@tonic-gate	leave
14947c478bd9Sstevel@tonic-gate	ret
14957c478bd9Sstevel@tonic-gate	SET_SIZE(copyin)
14967c478bd9Sstevel@tonic-gate
14977c478bd9Sstevel@tonic-gate#elif defined(__i386)
14987c478bd9Sstevel@tonic-gate
14997c478bd9Sstevel@tonic-gate#define	ARG_UADDR	4
15007c478bd9Sstevel@tonic-gate#define	ARG_KADDR	8
15017c478bd9Sstevel@tonic-gate
15027c478bd9Sstevel@tonic-gate	ENTRY(copyin)
15037c478bd9Sstevel@tonic-gate	movl	kernelbase, %ecx
15047c478bd9Sstevel@tonic-gate#ifdef DEBUG
15057c478bd9Sstevel@tonic-gate	cmpl	%ecx, ARG_KADDR(%esp)
15067c478bd9Sstevel@tonic-gate	jnb	1f
15077c478bd9Sstevel@tonic-gate	pushl	%ebp
15087c478bd9Sstevel@tonic-gate	movl	%esp, %ebp
15097c478bd9Sstevel@tonic-gate	pushl	$.copyin_panic_msg
15107c478bd9Sstevel@tonic-gate	call	panic
15117c478bd9Sstevel@tonic-gate1:
15127c478bd9Sstevel@tonic-gate#endif
15137c478bd9Sstevel@tonic-gate	lea	_copyin_err, %eax
15147c478bd9Sstevel@tonic-gate
15157c478bd9Sstevel@tonic-gate	movl	%gs:CPU_THREAD, %edx
15167c478bd9Sstevel@tonic-gate	cmpl	%ecx, ARG_UADDR(%esp)	/* test uaddr < kernelbase */
15177c478bd9Sstevel@tonic-gate	jb	do_copy_fault
15187c478bd9Sstevel@tonic-gate	jmp	3f
15197c478bd9Sstevel@tonic-gate
15207c478bd9Sstevel@tonic-gate_copyin_err:
15217c478bd9Sstevel@tonic-gate	popl	%ecx
15227c478bd9Sstevel@tonic-gate	popl	%edi
15237c478bd9Sstevel@tonic-gate	movl	%ecx, T_LOFAULT(%edx)	/* restore original lofault */
15247c478bd9Sstevel@tonic-gate	popl	%esi
15257c478bd9Sstevel@tonic-gate	popl	%ebp
15267c478bd9Sstevel@tonic-gate3:
15277c478bd9Sstevel@tonic-gate	movl	T_COPYOPS(%edx), %eax
15287c478bd9Sstevel@tonic-gate	cmpl	$0, %eax
15297c478bd9Sstevel@tonic-gate	jz	2f
15307c478bd9Sstevel@tonic-gate	jmp	*CP_COPYIN(%eax)
15317c478bd9Sstevel@tonic-gate
15327c478bd9Sstevel@tonic-gate2:	movl	$-1, %eax
15337c478bd9Sstevel@tonic-gate	ret
15347c478bd9Sstevel@tonic-gate	SET_SIZE(copyin)
15357c478bd9Sstevel@tonic-gate
15367c478bd9Sstevel@tonic-gate#undef	ARG_UADDR
15377c478bd9Sstevel@tonic-gate#undef	ARG_KADDR
15387c478bd9Sstevel@tonic-gate
15397c478bd9Sstevel@tonic-gate#endif	/* __i386 */
15407c478bd9Sstevel@tonic-gate#endif	/* __lint */
15417c478bd9Sstevel@tonic-gate
15427c478bd9Sstevel@tonic-gate#if defined(__lint)
15437c478bd9Sstevel@tonic-gate
15447c478bd9Sstevel@tonic-gate/* ARGSUSED */
15457c478bd9Sstevel@tonic-gateint
15467c478bd9Sstevel@tonic-gatexcopyin_nta(const void *uaddr, void *kaddr, size_t count, int copy_cached)
15477c478bd9Sstevel@tonic-gate{ return (0); }
15487c478bd9Sstevel@tonic-gate
15497c478bd9Sstevel@tonic-gate#else	/* __lint */
15507c478bd9Sstevel@tonic-gate
15517c478bd9Sstevel@tonic-gate#if defined(__amd64)
15527c478bd9Sstevel@tonic-gate
15537c478bd9Sstevel@tonic-gate	ENTRY(xcopyin_nta)
15547c478bd9Sstevel@tonic-gate	pushq	%rbp
15557c478bd9Sstevel@tonic-gate	movq	%rsp, %rbp
1556b08adf18SBill Holler	subq	$24, %rsp
15577c478bd9Sstevel@tonic-gate
15587c478bd9Sstevel@tonic-gate	/*
15597c478bd9Sstevel@tonic-gate	 * save args in case we trap and need to rerun as a copyop
15607c478bd9Sstevel@tonic-gate	 * %rcx is consumed in this routine so we don't need to save
15617c478bd9Sstevel@tonic-gate	 * it.
15627c478bd9Sstevel@tonic-gate	 */
15637c478bd9Sstevel@tonic-gate	movq	%rdi, (%rsp)
15647c478bd9Sstevel@tonic-gate	movq	%rsi, 0x8(%rsp)
15657c478bd9Sstevel@tonic-gate	movq	%rdx, 0x10(%rsp)
15667c478bd9Sstevel@tonic-gate
15677c478bd9Sstevel@tonic-gate	movq	kernelbase(%rip), %rax
15687c478bd9Sstevel@tonic-gate#ifdef DEBUG
15697c478bd9Sstevel@tonic-gate	cmpq	%rax, %rsi		/* %rsi = kaddr */
15707c478bd9Sstevel@tonic-gate	jnb	1f
15717c478bd9Sstevel@tonic-gate	leaq	.xcopyin_panic_msg(%rip), %rdi
15727c478bd9Sstevel@tonic-gate	xorl	%eax, %eax
15737c478bd9Sstevel@tonic-gate	call	panic
15747c478bd9Sstevel@tonic-gate1:
15757c478bd9Sstevel@tonic-gate#endif
15767c478bd9Sstevel@tonic-gate	movq	%gs:CPU_THREAD, %r9
15777c478bd9Sstevel@tonic-gate	cmpq	%rax, %rdi		/* test uaddr < kernelbase */
1578b737e79eSnn35248	jae	4f
15797c478bd9Sstevel@tonic-gate	cmpq	$0, %rcx		/* No non-temporal access? */
15807c478bd9Sstevel@tonic-gate	/*
15817c478bd9Sstevel@tonic-gate	 * pass lofault value as 4th argument to do_copy_fault
15827c478bd9Sstevel@tonic-gate	 */
15837c478bd9Sstevel@tonic-gate	leaq	_xcopyin_err(%rip), %rcx	/* doesn't set rflags */
15847c478bd9Sstevel@tonic-gate	jnz	do_copy_fault		/* use regular access */
15857c478bd9Sstevel@tonic-gate	/*
15867c478bd9Sstevel@tonic-gate	 * Make sure cnt is >= XCOPY_MIN_SIZE bytes
15877c478bd9Sstevel@tonic-gate	 */
15887c478bd9Sstevel@tonic-gate	cmpq	$XCOPY_MIN_SIZE, %rdx
15897c478bd9Sstevel@tonic-gate	jb	do_copy_fault
15907c478bd9Sstevel@tonic-gate
15917c478bd9Sstevel@tonic-gate	/*
15927c478bd9Sstevel@tonic-gate	 * Make sure src and dst are NTA_ALIGN_SIZE aligned,
15937c478bd9Sstevel@tonic-gate	 * count is COUNT_ALIGN_SIZE aligned.
15947c478bd9Sstevel@tonic-gate	 */
15957c478bd9Sstevel@tonic-gate	movq	%rdi, %r10
15967c478bd9Sstevel@tonic-gate	orq	%rsi, %r10
15977c478bd9Sstevel@tonic-gate	andq	$NTA_ALIGN_MASK, %r10
15987c478bd9Sstevel@tonic-gate	orq	%rdx, %r10
15997c478bd9Sstevel@tonic-gate	andq	$COUNT_ALIGN_MASK, %r10
16007c478bd9Sstevel@tonic-gate	jnz	do_copy_fault
1601b08adf18SBill Holler	leaq	_xcopyin_nta_err(%rip), %rcx	/* doesn't set rflags */
16027c478bd9Sstevel@tonic-gate	jmp	do_copy_fault_nta	/* use non-temporal access */
16037c478bd9Sstevel@tonic-gate
1604b737e79eSnn352484:
1605b737e79eSnn35248	movl	$EFAULT, %eax
1606b737e79eSnn35248	jmp	3f
1607b737e79eSnn35248
16087c478bd9Sstevel@tonic-gate	/*
16097c478bd9Sstevel@tonic-gate	 * A fault during do_copy_fault or do_copy_fault_nta is
16107c478bd9Sstevel@tonic-gate	 * indicated through an errno value in %rax and we iret from the
16117c478bd9Sstevel@tonic-gate	 * trap handler to here.
16127c478bd9Sstevel@tonic-gate	 */
16137c478bd9Sstevel@tonic-gate_xcopyin_err:
1614b08adf18SBill Holler	addq	$8, %rsp		/* pop bcopy_altentry call ret addr */
1615b08adf18SBill Holler_xcopyin_nta_err:
16167c478bd9Sstevel@tonic-gate	movq	%r11, T_LOFAULT(%r9)	/* restore original lofault */
16177c478bd9Sstevel@tonic-gate3:
16187c478bd9Sstevel@tonic-gate	movq	T_COPYOPS(%r9), %r8
16197c478bd9Sstevel@tonic-gate	cmpq	$0, %r8
16207c478bd9Sstevel@tonic-gate	jz	2f
16217c478bd9Sstevel@tonic-gate
16227c478bd9Sstevel@tonic-gate	/*
16237c478bd9Sstevel@tonic-gate	 * reload args for the copyop
16247c478bd9Sstevel@tonic-gate	 */
16257c478bd9Sstevel@tonic-gate	movq	(%rsp), %rdi
16267c478bd9Sstevel@tonic-gate	movq	0x8(%rsp), %rsi
16277c478bd9Sstevel@tonic-gate	movq	0x10(%rsp), %rdx
16287c478bd9Sstevel@tonic-gate	leave
16297c478bd9Sstevel@tonic-gate	jmp	*CP_XCOPYIN(%r8)
16307c478bd9Sstevel@tonic-gate
16317c478bd9Sstevel@tonic-gate2:	leave
16327c478bd9Sstevel@tonic-gate	ret
16337c478bd9Sstevel@tonic-gate	SET_SIZE(xcopyin_nta)
16347c478bd9Sstevel@tonic-gate
16357c478bd9Sstevel@tonic-gate#elif defined(__i386)
16367c478bd9Sstevel@tonic-gate
16377c478bd9Sstevel@tonic-gate#define	ARG_UADDR	4
16387c478bd9Sstevel@tonic-gate#define	ARG_KADDR	8
16397c478bd9Sstevel@tonic-gate#define	ARG_COUNT	12
16407c478bd9Sstevel@tonic-gate#define	ARG_CACHED	16
16417c478bd9Sstevel@tonic-gate
16427c478bd9Sstevel@tonic-gate	.globl	use_sse_copy
16437c478bd9Sstevel@tonic-gate
16447c478bd9Sstevel@tonic-gate	ENTRY(xcopyin_nta)
16457c478bd9Sstevel@tonic-gate	movl	kernelbase, %ecx
16467c478bd9Sstevel@tonic-gate	lea	_xcopyin_err, %eax
16477c478bd9Sstevel@tonic-gate	movl	%gs:CPU_THREAD, %edx
16487c478bd9Sstevel@tonic-gate	cmpl	%ecx, ARG_UADDR(%esp)	/* test uaddr < kernelbase */
1649b737e79eSnn35248	jae	4f
16507c478bd9Sstevel@tonic-gate
16517c478bd9Sstevel@tonic-gate	cmpl	$0, use_sse_copy	/* no sse support */
16527c478bd9Sstevel@tonic-gate	jz	do_copy_fault
16537c478bd9Sstevel@tonic-gate
16547c478bd9Sstevel@tonic-gate	cmpl	$0, ARG_CACHED(%esp)	/* copy_cached hint set? */
16557c478bd9Sstevel@tonic-gate	jnz	do_copy_fault
16567c478bd9Sstevel@tonic-gate
16577c478bd9Sstevel@tonic-gate	/*
16587c478bd9Sstevel@tonic-gate	 * Make sure cnt is >= XCOPY_MIN_SIZE bytes
16597c478bd9Sstevel@tonic-gate	 */
16607c478bd9Sstevel@tonic-gate	cmpl	$XCOPY_MIN_SIZE, ARG_COUNT(%esp)
16617c478bd9Sstevel@tonic-gate	jb	do_copy_fault
16627c478bd9Sstevel@tonic-gate
16637c478bd9Sstevel@tonic-gate	/*
16647c478bd9Sstevel@tonic-gate	 * Make sure src and dst are NTA_ALIGN_SIZE aligned,
16657c478bd9Sstevel@tonic-gate	 * count is COUNT_ALIGN_SIZE aligned.
16667c478bd9Sstevel@tonic-gate	 */
16677c478bd9Sstevel@tonic-gate	movl	ARG_UADDR(%esp), %ecx
16687c478bd9Sstevel@tonic-gate	orl	ARG_KADDR(%esp), %ecx
16697c478bd9Sstevel@tonic-gate	andl	$NTA_ALIGN_MASK, %ecx
16707c478bd9Sstevel@tonic-gate	orl	ARG_COUNT(%esp), %ecx
16717c478bd9Sstevel@tonic-gate	andl	$COUNT_ALIGN_MASK, %ecx
16727c478bd9Sstevel@tonic-gate	jnz	do_copy_fault
16737c478bd9Sstevel@tonic-gate
16747c478bd9Sstevel@tonic-gate	jmp	do_copy_fault_nta	/* use regular access */
16757c478bd9Sstevel@tonic-gate
1676b737e79eSnn352484:
1677b737e79eSnn35248	movl	$EFAULT, %eax
1678b737e79eSnn35248	jmp	3f
1679b737e79eSnn35248
16807c478bd9Sstevel@tonic-gate	/*
16817c478bd9Sstevel@tonic-gate	 * A fault during do_copy_fault or do_copy_fault_nta is
16827c478bd9Sstevel@tonic-gate	 * indicated through an errno value in %eax and we iret from the
16837c478bd9Sstevel@tonic-gate	 * trap handler to here.
16847c478bd9Sstevel@tonic-gate	 */
16857c478bd9Sstevel@tonic-gate_xcopyin_err:
16867c478bd9Sstevel@tonic-gate	popl	%ecx
16877c478bd9Sstevel@tonic-gate	popl	%edi
16887c478bd9Sstevel@tonic-gate	movl	%ecx, T_LOFAULT(%edx)	/* restore original lofault */
16897c478bd9Sstevel@tonic-gate	popl	%esi
16907c478bd9Sstevel@tonic-gate	popl	%ebp
16917c478bd9Sstevel@tonic-gate3:
16927c478bd9Sstevel@tonic-gate	cmpl	$0, T_COPYOPS(%edx)
16937c478bd9Sstevel@tonic-gate	jz	2f
16947c478bd9Sstevel@tonic-gate	movl	T_COPYOPS(%edx), %eax
16957c478bd9Sstevel@tonic-gate	jmp	*CP_XCOPYIN(%eax)
16967c478bd9Sstevel@tonic-gate
169785641879Skalai2:	rep; 	ret	/* use 2 byte return instruction when branch target */
169885641879Skalai			/* AMD Software Optimization Guide - Section 6.2 */
16997c478bd9Sstevel@tonic-gate	SET_SIZE(xcopyin_nta)
17007c478bd9Sstevel@tonic-gate
17017c478bd9Sstevel@tonic-gate#undef	ARG_UADDR
17027c478bd9Sstevel@tonic-gate#undef	ARG_KADDR
17037c478bd9Sstevel@tonic-gate#undef	ARG_COUNT
17047c478bd9Sstevel@tonic-gate#undef	ARG_CACHED
17057c478bd9Sstevel@tonic-gate
17067c478bd9Sstevel@tonic-gate#endif	/* __i386 */
17077c478bd9Sstevel@tonic-gate#endif	/* __lint */
17087c478bd9Sstevel@tonic-gate
17097c478bd9Sstevel@tonic-gate/*
17107c478bd9Sstevel@tonic-gate * Copy kernel data to user space.
17117c478bd9Sstevel@tonic-gate */
17127c478bd9Sstevel@tonic-gate
17137c478bd9Sstevel@tonic-gate#if defined(__lint)
17147c478bd9Sstevel@tonic-gate
17157c478bd9Sstevel@tonic-gate/* ARGSUSED */
17167c478bd9Sstevel@tonic-gateint
17177c478bd9Sstevel@tonic-gatecopyout(const void *kaddr, void *uaddr, size_t count)
17187c478bd9Sstevel@tonic-gate{ return (0); }
17197c478bd9Sstevel@tonic-gate
17207c478bd9Sstevel@tonic-gate#else	/* __lint */
17217c478bd9Sstevel@tonic-gate
17227c478bd9Sstevel@tonic-gate#if defined(__amd64)
17237c478bd9Sstevel@tonic-gate
17247c478bd9Sstevel@tonic-gate	ENTRY(copyout)
17257c478bd9Sstevel@tonic-gate	pushq	%rbp
17267c478bd9Sstevel@tonic-gate	movq	%rsp, %rbp
1727b08adf18SBill Holler	subq	$24, %rsp
17287c478bd9Sstevel@tonic-gate
17297c478bd9Sstevel@tonic-gate	/*
17307c478bd9Sstevel@tonic-gate	 * save args in case we trap and need to rerun as a copyop
17317c478bd9Sstevel@tonic-gate	 */
17327c478bd9Sstevel@tonic-gate	movq	%rdi, (%rsp)
17337c478bd9Sstevel@tonic-gate	movq	%rsi, 0x8(%rsp)
17347c478bd9Sstevel@tonic-gate	movq	%rdx, 0x10(%rsp)
17357c478bd9Sstevel@tonic-gate
17367c478bd9Sstevel@tonic-gate	movq	kernelbase(%rip), %rax
17377c478bd9Sstevel@tonic-gate#ifdef DEBUG
17387c478bd9Sstevel@tonic-gate	cmpq	%rax, %rdi		/* %rdi = kaddr */
17397c478bd9Sstevel@tonic-gate	jnb	1f
17407c478bd9Sstevel@tonic-gate	leaq	.copyout_panic_msg(%rip), %rdi
17417c478bd9Sstevel@tonic-gate	xorl	%eax, %eax
17427c478bd9Sstevel@tonic-gate	call	panic
17437c478bd9Sstevel@tonic-gate1:
17447c478bd9Sstevel@tonic-gate#endif
17457c478bd9Sstevel@tonic-gate	/*
17467c478bd9Sstevel@tonic-gate	 * pass lofault value as 4th argument to do_copy_fault
17477c478bd9Sstevel@tonic-gate	 */
17487c478bd9Sstevel@tonic-gate	leaq	_copyout_err(%rip), %rcx
17497c478bd9Sstevel@tonic-gate
17507c478bd9Sstevel@tonic-gate	movq	%gs:CPU_THREAD, %r9
17517c478bd9Sstevel@tonic-gate	cmpq	%rax, %rsi		/* test uaddr < kernelbase */
17527c478bd9Sstevel@tonic-gate	jb	do_copy_fault
17537c478bd9Sstevel@tonic-gate	jmp	3f
17547c478bd9Sstevel@tonic-gate
17557c478bd9Sstevel@tonic-gate_copyout_err:
17567c478bd9Sstevel@tonic-gate	movq	%r11, T_LOFAULT(%r9)	/* restore original lofault */
1757b08adf18SBill Holler	addq	$8, %rsp		/* pop bcopy_altentry call ret addr */
17587c478bd9Sstevel@tonic-gate3:
17597c478bd9Sstevel@tonic-gate	movq	T_COPYOPS(%r9), %rax
17607c478bd9Sstevel@tonic-gate	cmpq	$0, %rax
17617c478bd9Sstevel@tonic-gate	jz	2f
17627c478bd9Sstevel@tonic-gate
17637c478bd9Sstevel@tonic-gate	/*
17647c478bd9Sstevel@tonic-gate	 * reload args for the copyop
17657c478bd9Sstevel@tonic-gate	 */
17667c478bd9Sstevel@tonic-gate	movq	(%rsp), %rdi
17677c478bd9Sstevel@tonic-gate	movq	0x8(%rsp), %rsi
17687c478bd9Sstevel@tonic-gate	movq	0x10(%rsp), %rdx
17697c478bd9Sstevel@tonic-gate	leave
17707c478bd9Sstevel@tonic-gate	jmp	*CP_COPYOUT(%rax)
17717c478bd9Sstevel@tonic-gate
17727c478bd9Sstevel@tonic-gate2:	movl	$-1, %eax
17737c478bd9Sstevel@tonic-gate	leave
17747c478bd9Sstevel@tonic-gate	ret
17757c478bd9Sstevel@tonic-gate	SET_SIZE(copyout)
17767c478bd9Sstevel@tonic-gate
17777c478bd9Sstevel@tonic-gate#elif defined(__i386)
17787c478bd9Sstevel@tonic-gate
17797c478bd9Sstevel@tonic-gate#define	ARG_KADDR	4
17807c478bd9Sstevel@tonic-gate#define	ARG_UADDR	8
17817c478bd9Sstevel@tonic-gate
17827c478bd9Sstevel@tonic-gate	ENTRY(copyout)
17837c478bd9Sstevel@tonic-gate	movl	kernelbase, %ecx
17847c478bd9Sstevel@tonic-gate#ifdef DEBUG
17857c478bd9Sstevel@tonic-gate	cmpl	%ecx, ARG_KADDR(%esp)
17867c478bd9Sstevel@tonic-gate	jnb	1f
17877c478bd9Sstevel@tonic-gate	pushl	%ebp
17887c478bd9Sstevel@tonic-gate	movl	%esp, %ebp
17897c478bd9Sstevel@tonic-gate	pushl	$.copyout_panic_msg
17907c478bd9Sstevel@tonic-gate	call	panic
17917c478bd9Sstevel@tonic-gate1:
17927c478bd9Sstevel@tonic-gate#endif
17937c478bd9Sstevel@tonic-gate	lea	_copyout_err, %eax
17947c478bd9Sstevel@tonic-gate	movl	%gs:CPU_THREAD, %edx
17957c478bd9Sstevel@tonic-gate	cmpl	%ecx, ARG_UADDR(%esp)	/* test uaddr < kernelbase */
17967c478bd9Sstevel@tonic-gate	jb	do_copy_fault
17977c478bd9Sstevel@tonic-gate	jmp	3f
17987c478bd9Sstevel@tonic-gate
17997c478bd9Sstevel@tonic-gate_copyout_err:
18007c478bd9Sstevel@tonic-gate	popl	%ecx
18017c478bd9Sstevel@tonic-gate	popl	%edi
18027c478bd9Sstevel@tonic-gate	movl	%ecx, T_LOFAULT(%edx)	/* restore original lofault */
18037c478bd9Sstevel@tonic-gate	popl	%esi
18047c478bd9Sstevel@tonic-gate	popl	%ebp
18057c478bd9Sstevel@tonic-gate3:
18067c478bd9Sstevel@tonic-gate	movl	T_COPYOPS(%edx), %eax
18077c478bd9Sstevel@tonic-gate	cmpl	$0, %eax
18087c478bd9Sstevel@tonic-gate	jz	2f
18097c478bd9Sstevel@tonic-gate	jmp	*CP_COPYOUT(%eax)
18107c478bd9Sstevel@tonic-gate
18117c478bd9Sstevel@tonic-gate2:	movl	$-1, %eax
18127c478bd9Sstevel@tonic-gate	ret
18137c478bd9Sstevel@tonic-gate	SET_SIZE(copyout)
18147c478bd9Sstevel@tonic-gate
18157c478bd9Sstevel@tonic-gate#undef	ARG_UADDR
18167c478bd9Sstevel@tonic-gate#undef	ARG_KADDR
18177c478bd9Sstevel@tonic-gate
18187c478bd9Sstevel@tonic-gate#endif	/* __i386 */
18197c478bd9Sstevel@tonic-gate#endif	/* __lint */
18207c478bd9Sstevel@tonic-gate
18217c478bd9Sstevel@tonic-gate#if defined(__lint)
18227c478bd9Sstevel@tonic-gate
18237c478bd9Sstevel@tonic-gate/* ARGSUSED */
18247c478bd9Sstevel@tonic-gateint
18257c478bd9Sstevel@tonic-gatexcopyout_nta(const void *kaddr, void *uaddr, size_t count, int copy_cached)
18267c478bd9Sstevel@tonic-gate{ return (0); }
18277c478bd9Sstevel@tonic-gate
18287c478bd9Sstevel@tonic-gate#else	/* __lint */
18297c478bd9Sstevel@tonic-gate
18307c478bd9Sstevel@tonic-gate#if defined(__amd64)
18317c478bd9Sstevel@tonic-gate
18327c478bd9Sstevel@tonic-gate	ENTRY(xcopyout_nta)
18337c478bd9Sstevel@tonic-gate	pushq	%rbp
18347c478bd9Sstevel@tonic-gate	movq	%rsp, %rbp
1835b08adf18SBill Holler	subq	$24, %rsp
18367c478bd9Sstevel@tonic-gate
18377c478bd9Sstevel@tonic-gate	/*
18387c478bd9Sstevel@tonic-gate	 * save args in case we trap and need to rerun as a copyop
18397c478bd9Sstevel@tonic-gate	 */
18407c478bd9Sstevel@tonic-gate	movq	%rdi, (%rsp)
18417c478bd9Sstevel@tonic-gate	movq	%rsi, 0x8(%rsp)
18427c478bd9Sstevel@tonic-gate	movq	%rdx, 0x10(%rsp)
18437c478bd9Sstevel@tonic-gate
18447c478bd9Sstevel@tonic-gate	movq	kernelbase(%rip), %rax
18457c478bd9Sstevel@tonic-gate#ifdef DEBUG
18467c478bd9Sstevel@tonic-gate	cmpq	%rax, %rdi		/* %rdi = kaddr */
18477c478bd9Sstevel@tonic-gate	jnb	1f
18487c478bd9Sstevel@tonic-gate	leaq	.xcopyout_panic_msg(%rip), %rdi
18497c478bd9Sstevel@tonic-gate	xorl	%eax, %eax
18507c478bd9Sstevel@tonic-gate	call	panic
18517c478bd9Sstevel@tonic-gate1:
18527c478bd9Sstevel@tonic-gate#endif
18537c478bd9Sstevel@tonic-gate	movq	%gs:CPU_THREAD, %r9
18547c478bd9Sstevel@tonic-gate	cmpq	%rax, %rsi		/* test uaddr < kernelbase */
1855b737e79eSnn35248	jae	4f
18567c478bd9Sstevel@tonic-gate
18577c478bd9Sstevel@tonic-gate	cmpq	$0, %rcx		/* No non-temporal access? */
18587c478bd9Sstevel@tonic-gate	/*
18597c478bd9Sstevel@tonic-gate	 * pass lofault value as 4th argument to do_copy_fault
18607c478bd9Sstevel@tonic-gate	 */
18617c478bd9Sstevel@tonic-gate	leaq	_xcopyout_err(%rip), %rcx
18627c478bd9Sstevel@tonic-gate	jnz	do_copy_fault
18637c478bd9Sstevel@tonic-gate	/*
18647c478bd9Sstevel@tonic-gate	 * Make sure cnt is >= XCOPY_MIN_SIZE bytes
18657c478bd9Sstevel@tonic-gate	 */
18667c478bd9Sstevel@tonic-gate	cmpq	$XCOPY_MIN_SIZE, %rdx
18677c478bd9Sstevel@tonic-gate	jb	do_copy_fault
18687c478bd9Sstevel@tonic-gate
18697c478bd9Sstevel@tonic-gate	/*
18707c478bd9Sstevel@tonic-gate	 * Make sure src and dst are NTA_ALIGN_SIZE aligned,
18717c478bd9Sstevel@tonic-gate	 * count is COUNT_ALIGN_SIZE aligned.
18727c478bd9Sstevel@tonic-gate	 */
18737c478bd9Sstevel@tonic-gate	movq	%rdi, %r10
18747c478bd9Sstevel@tonic-gate	orq	%rsi, %r10
18757c478bd9Sstevel@tonic-gate	andq	$NTA_ALIGN_MASK, %r10
18767c478bd9Sstevel@tonic-gate	orq	%rdx, %r10
18777c478bd9Sstevel@tonic-gate	andq	$COUNT_ALIGN_MASK, %r10
18787c478bd9Sstevel@tonic-gate	jnz	do_copy_fault
1879b08adf18SBill Holler	leaq	_xcopyout_nta_err(%rip), %rcx
18807c478bd9Sstevel@tonic-gate	jmp	do_copy_fault_nta
18817c478bd9Sstevel@tonic-gate
1882b737e79eSnn352484:
1883b737e79eSnn35248	movl	$EFAULT, %eax
1884b737e79eSnn35248	jmp	3f
1885b737e79eSnn35248
18867c478bd9Sstevel@tonic-gate	/*
18877c478bd9Sstevel@tonic-gate	 * A fault during do_copy_fault or do_copy_fault_nta is
18887c478bd9Sstevel@tonic-gate	 * indicated through an errno value in %rax and we iret from the
18897c478bd9Sstevel@tonic-gate	 * trap handler to here.
18907c478bd9Sstevel@tonic-gate	 */
18917c478bd9Sstevel@tonic-gate_xcopyout_err:
1892b08adf18SBill Holler	addq	$8, %rsp		/* pop bcopy_altentry call ret addr */
1893b08adf18SBill Holler_xcopyout_nta_err:
18947c478bd9Sstevel@tonic-gate	movq	%r11, T_LOFAULT(%r9)	/* restore original lofault */
18957c478bd9Sstevel@tonic-gate3:
18967c478bd9Sstevel@tonic-gate	movq	T_COPYOPS(%r9), %r8
18977c478bd9Sstevel@tonic-gate	cmpq	$0, %r8
18987c478bd9Sstevel@tonic-gate	jz	2f
18997c478bd9Sstevel@tonic-gate
19007c478bd9Sstevel@tonic-gate	/*
19017c478bd9Sstevel@tonic-gate	 * reload args for the copyop
19027c478bd9Sstevel@tonic-gate	 */
19037c478bd9Sstevel@tonic-gate	movq	(%rsp), %rdi
19047c478bd9Sstevel@tonic-gate	movq	0x8(%rsp), %rsi
19057c478bd9Sstevel@tonic-gate	movq	0x10(%rsp), %rdx
19067c478bd9Sstevel@tonic-gate	leave
19077c478bd9Sstevel@tonic-gate	jmp	*CP_XCOPYOUT(%r8)
19087c478bd9Sstevel@tonic-gate
19097c478bd9Sstevel@tonic-gate2:	leave
19107c478bd9Sstevel@tonic-gate	ret
19117c478bd9Sstevel@tonic-gate	SET_SIZE(xcopyout_nta)
19127c478bd9Sstevel@tonic-gate
19137c478bd9Sstevel@tonic-gate#elif defined(__i386)
19147c478bd9Sstevel@tonic-gate
19157c478bd9Sstevel@tonic-gate#define	ARG_KADDR	4
19167c478bd9Sstevel@tonic-gate#define	ARG_UADDR	8
19177c478bd9Sstevel@tonic-gate#define	ARG_COUNT	12
19187c478bd9Sstevel@tonic-gate#define	ARG_CACHED	16
19197c478bd9Sstevel@tonic-gate
19207c478bd9Sstevel@tonic-gate	ENTRY(xcopyout_nta)
19217c478bd9Sstevel@tonic-gate	movl	kernelbase, %ecx
19227c478bd9Sstevel@tonic-gate	lea	_xcopyout_err, %eax
19237c478bd9Sstevel@tonic-gate	movl	%gs:CPU_THREAD, %edx
19247c478bd9Sstevel@tonic-gate	cmpl	%ecx, ARG_UADDR(%esp)	/* test uaddr < kernelbase */
1925b737e79eSnn35248	jae	4f
19267c478bd9Sstevel@tonic-gate
19277c478bd9Sstevel@tonic-gate	cmpl	$0, use_sse_copy	/* no sse support */
19287c478bd9Sstevel@tonic-gate	jz	do_copy_fault
19297c478bd9Sstevel@tonic-gate
19307c478bd9Sstevel@tonic-gate	cmpl	$0, ARG_CACHED(%esp)	/* copy_cached hint set? */
19317c478bd9Sstevel@tonic-gate	jnz	do_copy_fault
19327c478bd9Sstevel@tonic-gate
19337c478bd9Sstevel@tonic-gate	/*
19347c478bd9Sstevel@tonic-gate	 * Make sure cnt is >= XCOPY_MIN_SIZE bytes
19357c478bd9Sstevel@tonic-gate	 */
19367c478bd9Sstevel@tonic-gate	cmpl	$XCOPY_MIN_SIZE, %edx
19377c478bd9Sstevel@tonic-gate	jb	do_copy_fault
19387c478bd9Sstevel@tonic-gate
19397c478bd9Sstevel@tonic-gate	/*
19407c478bd9Sstevel@tonic-gate	 * Make sure src and dst are NTA_ALIGN_SIZE aligned,
19417c478bd9Sstevel@tonic-gate	 * count is COUNT_ALIGN_SIZE aligned.
19427c478bd9Sstevel@tonic-gate	 */
19437c478bd9Sstevel@tonic-gate	movl	ARG_UADDR(%esp), %ecx
19447c478bd9Sstevel@tonic-gate	orl	ARG_KADDR(%esp), %ecx
19457c478bd9Sstevel@tonic-gate	andl	$NTA_ALIGN_MASK, %ecx
19467c478bd9Sstevel@tonic-gate	orl	ARG_COUNT(%esp), %ecx
19477c478bd9Sstevel@tonic-gate	andl	$COUNT_ALIGN_MASK, %ecx
19487c478bd9Sstevel@tonic-gate	jnz	do_copy_fault
19497c478bd9Sstevel@tonic-gate	jmp	do_copy_fault_nta
19507c478bd9Sstevel@tonic-gate
1951b737e79eSnn352484:
1952b737e79eSnn35248	movl	$EFAULT, %eax
1953b737e79eSnn35248	jmp	3f
1954b737e79eSnn35248
19557c478bd9Sstevel@tonic-gate	/*
19567c478bd9Sstevel@tonic-gate	 * A fault during do_copy_fault or do_copy_fault_nta is
19577c478bd9Sstevel@tonic-gate	 * indicated through an errno value in %eax and we iret from the
19587c478bd9Sstevel@tonic-gate	 * trap handler to here.
19597c478bd9Sstevel@tonic-gate	 */
19607c478bd9Sstevel@tonic-gate_xcopyout_err:
19617c478bd9Sstevel@tonic-gate	/ restore the original lofault
19627c478bd9Sstevel@tonic-gate	popl	%ecx
19637c478bd9Sstevel@tonic-gate	popl	%edi
19647c478bd9Sstevel@tonic-gate	movl	%ecx, T_LOFAULT(%edx)	/ original lofault
19657c478bd9Sstevel@tonic-gate	popl	%esi
19667c478bd9Sstevel@tonic-gate	popl	%ebp
19677c478bd9Sstevel@tonic-gate3:
19687c478bd9Sstevel@tonic-gate	cmpl	$0, T_COPYOPS(%edx)
19697c478bd9Sstevel@tonic-gate	jz	2f
19707c478bd9Sstevel@tonic-gate	movl	T_COPYOPS(%edx), %eax
19717c478bd9Sstevel@tonic-gate	jmp	*CP_XCOPYOUT(%eax)
19727c478bd9Sstevel@tonic-gate
197385641879Skalai2:	rep;	ret	/* use 2 byte return instruction when branch target */
197485641879Skalai			/* AMD Software Optimization Guide - Section 6.2 */
19757c478bd9Sstevel@tonic-gate	SET_SIZE(xcopyout_nta)
19767c478bd9Sstevel@tonic-gate
19777c478bd9Sstevel@tonic-gate#undef	ARG_UADDR
19787c478bd9Sstevel@tonic-gate#undef	ARG_KADDR
19797c478bd9Sstevel@tonic-gate#undef	ARG_COUNT
19807c478bd9Sstevel@tonic-gate#undef	ARG_CACHED
19817c478bd9Sstevel@tonic-gate
19827c478bd9Sstevel@tonic-gate#endif	/* __i386 */
19837c478bd9Sstevel@tonic-gate#endif	/* __lint */
19847c478bd9Sstevel@tonic-gate
19857c478bd9Sstevel@tonic-gate/*
19867c478bd9Sstevel@tonic-gate * Copy a null terminated string from one point to another in
19877c478bd9Sstevel@tonic-gate * the kernel address space.
19887c478bd9Sstevel@tonic-gate */
19897c478bd9Sstevel@tonic-gate
19907c478bd9Sstevel@tonic-gate#if defined(__lint)
19917c478bd9Sstevel@tonic-gate
19927c478bd9Sstevel@tonic-gate/* ARGSUSED */
19937c478bd9Sstevel@tonic-gateint
19947c478bd9Sstevel@tonic-gatecopystr(const char *from, char *to, size_t maxlength, size_t *lencopied)
19957c478bd9Sstevel@tonic-gate{ return (0); }
19967c478bd9Sstevel@tonic-gate
19977c478bd9Sstevel@tonic-gate#else	/* __lint */
19987c478bd9Sstevel@tonic-gate
19997c478bd9Sstevel@tonic-gate#if defined(__amd64)
20007c478bd9Sstevel@tonic-gate
20017c478bd9Sstevel@tonic-gate	ENTRY(copystr)
20027c478bd9Sstevel@tonic-gate	pushq	%rbp
20037c478bd9Sstevel@tonic-gate	movq	%rsp, %rbp
20047c478bd9Sstevel@tonic-gate#ifdef DEBUG
20057c478bd9Sstevel@tonic-gate	movq	kernelbase(%rip), %rax
20067c478bd9Sstevel@tonic-gate	cmpq	%rax, %rdi		/* %rdi = from */
20077c478bd9Sstevel@tonic-gate	jb	0f
20087c478bd9Sstevel@tonic-gate	cmpq	%rax, %rsi		/* %rsi = to */
20097c478bd9Sstevel@tonic-gate	jnb	1f
20107c478bd9Sstevel@tonic-gate0:	leaq	.copystr_panic_msg(%rip), %rdi
20117c478bd9Sstevel@tonic-gate	xorl	%eax, %eax
20127c478bd9Sstevel@tonic-gate	call	panic
20137c478bd9Sstevel@tonic-gate1:
20147c478bd9Sstevel@tonic-gate#endif
20157c478bd9Sstevel@tonic-gate	movq	%gs:CPU_THREAD, %r9
20167c478bd9Sstevel@tonic-gate	movq	T_LOFAULT(%r9), %r8	/* pass current lofault value as */
20177c478bd9Sstevel@tonic-gate					/* 5th argument to do_copystr */
20187c478bd9Sstevel@tonic-gatedo_copystr:
20197c478bd9Sstevel@tonic-gate	movq	%gs:CPU_THREAD, %r9	/* %r9 = thread addr */
20207c478bd9Sstevel@tonic-gate	movq    T_LOFAULT(%r9), %r11	/* save the current lofault */
20217c478bd9Sstevel@tonic-gate	movq	%r8, T_LOFAULT(%r9)	/* new lofault */
20227c478bd9Sstevel@tonic-gate
20237c478bd9Sstevel@tonic-gate	movq	%rdx, %r8		/* save maxlength */
20247c478bd9Sstevel@tonic-gate
20257c478bd9Sstevel@tonic-gate	cmpq	$0, %rdx		/* %rdx = maxlength */
20267c478bd9Sstevel@tonic-gate	je	copystr_enametoolong	/* maxlength == 0 */
20277c478bd9Sstevel@tonic-gate
20287c478bd9Sstevel@tonic-gatecopystr_loop:
20297c478bd9Sstevel@tonic-gate	decq	%r8
20307c478bd9Sstevel@tonic-gate	movb	(%rdi), %al
20317c478bd9Sstevel@tonic-gate	incq	%rdi
20327c478bd9Sstevel@tonic-gate	movb	%al, (%rsi)
20337c478bd9Sstevel@tonic-gate	incq	%rsi
20347c478bd9Sstevel@tonic-gate	cmpb	$0, %al
20357c478bd9Sstevel@tonic-gate	je	copystr_null		/* null char */
20367c478bd9Sstevel@tonic-gate	cmpq	$0, %r8
20377c478bd9Sstevel@tonic-gate	jne	copystr_loop
20387c478bd9Sstevel@tonic-gate
20397c478bd9Sstevel@tonic-gatecopystr_enametoolong:
20407c478bd9Sstevel@tonic-gate	movl	$ENAMETOOLONG, %eax
20417c478bd9Sstevel@tonic-gate	jmp	copystr_out
20427c478bd9Sstevel@tonic-gate
20437c478bd9Sstevel@tonic-gatecopystr_null:
20447c478bd9Sstevel@tonic-gate	xorl	%eax, %eax		/* no error */
20457c478bd9Sstevel@tonic-gate
20467c478bd9Sstevel@tonic-gatecopystr_out:
20477c478bd9Sstevel@tonic-gate	cmpq	$0, %rcx		/* want length? */
20487c478bd9Sstevel@tonic-gate	je	copystr_done		/* no */
20497c478bd9Sstevel@tonic-gate	subq	%r8, %rdx		/* compute length and store it */
20507c478bd9Sstevel@tonic-gate	movq	%rdx, (%rcx)
20517c478bd9Sstevel@tonic-gate
20527c478bd9Sstevel@tonic-gatecopystr_done:
20537c478bd9Sstevel@tonic-gate	movq	%r11, T_LOFAULT(%r9)	/* restore the original lofault */
20547c478bd9Sstevel@tonic-gate	leave
20557c478bd9Sstevel@tonic-gate	ret
20567c478bd9Sstevel@tonic-gate	SET_SIZE(copystr)
20577c478bd9Sstevel@tonic-gate
20587c478bd9Sstevel@tonic-gate#elif defined(__i386)
20597c478bd9Sstevel@tonic-gate
20607c478bd9Sstevel@tonic-gate#define	ARG_FROM	8
20617c478bd9Sstevel@tonic-gate#define	ARG_TO		12
20627c478bd9Sstevel@tonic-gate#define	ARG_MAXLEN	16
20637c478bd9Sstevel@tonic-gate#define	ARG_LENCOPIED	20
20647c478bd9Sstevel@tonic-gate
20657c478bd9Sstevel@tonic-gate	ENTRY(copystr)
20667c478bd9Sstevel@tonic-gate#ifdef DEBUG
20677c478bd9Sstevel@tonic-gate	pushl	%ebp
20687c478bd9Sstevel@tonic-gate	movl	%esp, %ebp
20697c478bd9Sstevel@tonic-gate	movl	kernelbase, %eax
20707c478bd9Sstevel@tonic-gate	cmpl	%eax, ARG_FROM(%esp)
20717c478bd9Sstevel@tonic-gate	jb	0f
20727c478bd9Sstevel@tonic-gate	cmpl	%eax, ARG_TO(%esp)
20737c478bd9Sstevel@tonic-gate	jnb	1f
20747c478bd9Sstevel@tonic-gate0:	pushl	$.copystr_panic_msg
20757c478bd9Sstevel@tonic-gate	call	panic
20767c478bd9Sstevel@tonic-gate1:	popl	%ebp
20777c478bd9Sstevel@tonic-gate#endif
20787c478bd9Sstevel@tonic-gate	/* get the current lofault address */
20797c478bd9Sstevel@tonic-gate	movl	%gs:CPU_THREAD, %eax
20807c478bd9Sstevel@tonic-gate	movl	T_LOFAULT(%eax), %eax
20817c478bd9Sstevel@tonic-gatedo_copystr:
20827c478bd9Sstevel@tonic-gate	pushl	%ebp			/* setup stack frame */
20837c478bd9Sstevel@tonic-gate	movl	%esp, %ebp
20847c478bd9Sstevel@tonic-gate	pushl	%ebx			/* save registers */
20857c478bd9Sstevel@tonic-gate	pushl	%edi
20867c478bd9Sstevel@tonic-gate
20877c478bd9Sstevel@tonic-gate	movl	%gs:CPU_THREAD, %ebx
20887c478bd9Sstevel@tonic-gate	movl	T_LOFAULT(%ebx), %edi
20897c478bd9Sstevel@tonic-gate	pushl	%edi			/* save the current lofault */
20907c478bd9Sstevel@tonic-gate	movl	%eax, T_LOFAULT(%ebx)	/* new lofault */
20917c478bd9Sstevel@tonic-gate
20927c478bd9Sstevel@tonic-gate	movl	ARG_MAXLEN(%ebp), %ecx
20937c478bd9Sstevel@tonic-gate	cmpl	$0, %ecx
20947c478bd9Sstevel@tonic-gate	je	copystr_enametoolong	/* maxlength == 0 */
20957c478bd9Sstevel@tonic-gate
20967c478bd9Sstevel@tonic-gate	movl	ARG_FROM(%ebp), %ebx	/* source address */
20977c478bd9Sstevel@tonic-gate	movl	ARG_TO(%ebp), %edx	/* destination address */
20987c478bd9Sstevel@tonic-gate
20997c478bd9Sstevel@tonic-gatecopystr_loop:
21007c478bd9Sstevel@tonic-gate	decl	%ecx
21017c478bd9Sstevel@tonic-gate	movb	(%ebx), %al
21027c478bd9Sstevel@tonic-gate	incl	%ebx
21037c478bd9Sstevel@tonic-gate	movb	%al, (%edx)
21047c478bd9Sstevel@tonic-gate	incl	%edx
21057c478bd9Sstevel@tonic-gate	cmpb	$0, %al
21067c478bd9Sstevel@tonic-gate	je	copystr_null		/* null char */
21077c478bd9Sstevel@tonic-gate	cmpl	$0, %ecx
21087c478bd9Sstevel@tonic-gate	jne	copystr_loop
21097c478bd9Sstevel@tonic-gate
21107c478bd9Sstevel@tonic-gatecopystr_enametoolong:
21117c478bd9Sstevel@tonic-gate	movl	$ENAMETOOLONG, %eax
21127c478bd9Sstevel@tonic-gate	jmp	copystr_out
21137c478bd9Sstevel@tonic-gate
21147c478bd9Sstevel@tonic-gatecopystr_null:
21157c478bd9Sstevel@tonic-gate	xorl	%eax, %eax		/* no error */
21167c478bd9Sstevel@tonic-gate
21177c478bd9Sstevel@tonic-gatecopystr_out:
21187c478bd9Sstevel@tonic-gate	cmpl	$0, ARG_LENCOPIED(%ebp)	/* want length? */
21197c478bd9Sstevel@tonic-gate	je	copystr_done		/* no */
21207c478bd9Sstevel@tonic-gate	movl	ARG_MAXLEN(%ebp), %edx
21217c478bd9Sstevel@tonic-gate	subl	%ecx, %edx		/* compute length and store it */
21227c478bd9Sstevel@tonic-gate	movl	ARG_LENCOPIED(%ebp), %ecx
21237c478bd9Sstevel@tonic-gate	movl	%edx, (%ecx)
21247c478bd9Sstevel@tonic-gate
21257c478bd9Sstevel@tonic-gatecopystr_done:
21267c478bd9Sstevel@tonic-gate	popl	%edi
21277c478bd9Sstevel@tonic-gate	movl	%gs:CPU_THREAD, %ebx
21287c478bd9Sstevel@tonic-gate	movl	%edi, T_LOFAULT(%ebx)	/* restore the original lofault */
21297c478bd9Sstevel@tonic-gate
21307c478bd9Sstevel@tonic-gate	popl	%edi
21317c478bd9Sstevel@tonic-gate	popl	%ebx
21327c478bd9Sstevel@tonic-gate	popl	%ebp
21337c478bd9Sstevel@tonic-gate	ret
21347c478bd9Sstevel@tonic-gate	SET_SIZE(copystr)
21357c478bd9Sstevel@tonic-gate
21367c478bd9Sstevel@tonic-gate#undef	ARG_FROM
21377c478bd9Sstevel@tonic-gate#undef	ARG_TO
21387c478bd9Sstevel@tonic-gate#undef	ARG_MAXLEN
21397c478bd9Sstevel@tonic-gate#undef	ARG_LENCOPIED
21407c478bd9Sstevel@tonic-gate
21417c478bd9Sstevel@tonic-gate#endif	/* __i386 */
21427c478bd9Sstevel@tonic-gate#endif	/* __lint */
21437c478bd9Sstevel@tonic-gate
21447c478bd9Sstevel@tonic-gate/*
21457c478bd9Sstevel@tonic-gate * Copy a null terminated string from the user address space into
21467c478bd9Sstevel@tonic-gate * the kernel address space.
21477c478bd9Sstevel@tonic-gate */
21487c478bd9Sstevel@tonic-gate
21497c478bd9Sstevel@tonic-gate#if defined(__lint)
21507c478bd9Sstevel@tonic-gate
21517c478bd9Sstevel@tonic-gate/* ARGSUSED */
21527c478bd9Sstevel@tonic-gateint
21537c478bd9Sstevel@tonic-gatecopyinstr(const char *uaddr, char *kaddr, size_t maxlength,
21547c478bd9Sstevel@tonic-gate    size_t *lencopied)
21557c478bd9Sstevel@tonic-gate{ return (0); }
21567c478bd9Sstevel@tonic-gate
21577c478bd9Sstevel@tonic-gate#else	/* __lint */
21587c478bd9Sstevel@tonic-gate
21597c478bd9Sstevel@tonic-gate#if defined(__amd64)
21607c478bd9Sstevel@tonic-gate
21617c478bd9Sstevel@tonic-gate	ENTRY(copyinstr)
21627c478bd9Sstevel@tonic-gate	pushq	%rbp
21637c478bd9Sstevel@tonic-gate	movq	%rsp, %rbp
21647c478bd9Sstevel@tonic-gate	subq	$32, %rsp
21657c478bd9Sstevel@tonic-gate
21667c478bd9Sstevel@tonic-gate	/*
21677c478bd9Sstevel@tonic-gate	 * save args in case we trap and need to rerun as a copyop
21687c478bd9Sstevel@tonic-gate	 */
21697c478bd9Sstevel@tonic-gate	movq	%rdi, (%rsp)
21707c478bd9Sstevel@tonic-gate	movq	%rsi, 0x8(%rsp)
21717c478bd9Sstevel@tonic-gate	movq	%rdx, 0x10(%rsp)
21727c478bd9Sstevel@tonic-gate	movq	%rcx, 0x18(%rsp)
21737c478bd9Sstevel@tonic-gate
21747c478bd9Sstevel@tonic-gate	movq	kernelbase(%rip), %rax
21757c478bd9Sstevel@tonic-gate#ifdef DEBUG
21767c478bd9Sstevel@tonic-gate	cmpq	%rax, %rsi		/* %rsi = kaddr */
21777c478bd9Sstevel@tonic-gate	jnb	1f
21787c478bd9Sstevel@tonic-gate	leaq	.copyinstr_panic_msg(%rip), %rdi
21797c478bd9Sstevel@tonic-gate	xorl	%eax, %eax
21807c478bd9Sstevel@tonic-gate	call	panic
21817c478bd9Sstevel@tonic-gate1:
21827c478bd9Sstevel@tonic-gate#endif
21837c478bd9Sstevel@tonic-gate	/*
21847c478bd9Sstevel@tonic-gate	 * pass lofault value as 5th argument to do_copystr
21857c478bd9Sstevel@tonic-gate	 */
21867c478bd9Sstevel@tonic-gate	leaq	_copyinstr_error(%rip), %r8
21877c478bd9Sstevel@tonic-gate
21887c478bd9Sstevel@tonic-gate	cmpq	%rax, %rdi		/* test uaddr < kernelbase */
21897c478bd9Sstevel@tonic-gate	jb	do_copystr
21907c478bd9Sstevel@tonic-gate	movq	%gs:CPU_THREAD, %r9
21917c478bd9Sstevel@tonic-gate	jmp	3f
21927c478bd9Sstevel@tonic-gate
21937c478bd9Sstevel@tonic-gate_copyinstr_error:
21947c478bd9Sstevel@tonic-gate	movq	%r11, T_LOFAULT(%r9)	/* restore original lofault */
21957c478bd9Sstevel@tonic-gate3:
21967c478bd9Sstevel@tonic-gate	movq	T_COPYOPS(%r9), %rax
21977c478bd9Sstevel@tonic-gate	cmpq	$0, %rax
21987c478bd9Sstevel@tonic-gate	jz	2f
21997c478bd9Sstevel@tonic-gate
22007c478bd9Sstevel@tonic-gate	/*
22017c478bd9Sstevel@tonic-gate	 * reload args for the copyop
22027c478bd9Sstevel@tonic-gate	 */
22037c478bd9Sstevel@tonic-gate	movq	(%rsp), %rdi
22047c478bd9Sstevel@tonic-gate	movq	0x8(%rsp), %rsi
22057c478bd9Sstevel@tonic-gate	movq	0x10(%rsp), %rdx
22067c478bd9Sstevel@tonic-gate	movq	0x18(%rsp), %rcx
22077c478bd9Sstevel@tonic-gate	leave
22087c478bd9Sstevel@tonic-gate	jmp	*CP_COPYINSTR(%rax)
22097c478bd9Sstevel@tonic-gate
22107c478bd9Sstevel@tonic-gate2:	movl	$EFAULT, %eax		/* return EFAULT */
22117c478bd9Sstevel@tonic-gate	leave
22127c478bd9Sstevel@tonic-gate	ret
22137c478bd9Sstevel@tonic-gate	SET_SIZE(copyinstr)
22147c478bd9Sstevel@tonic-gate
22157c478bd9Sstevel@tonic-gate#elif defined(__i386)
22167c478bd9Sstevel@tonic-gate
22177c478bd9Sstevel@tonic-gate#define	ARG_UADDR	4
22187c478bd9Sstevel@tonic-gate#define	ARG_KADDR	8
22197c478bd9Sstevel@tonic-gate
22207c478bd9Sstevel@tonic-gate	ENTRY(copyinstr)
22217c478bd9Sstevel@tonic-gate	movl	kernelbase, %ecx
22227c478bd9Sstevel@tonic-gate#ifdef DEBUG
22237c478bd9Sstevel@tonic-gate	cmpl	%ecx, ARG_KADDR(%esp)
22247c478bd9Sstevel@tonic-gate	jnb	1f
22257c478bd9Sstevel@tonic-gate	pushl	%ebp
22267c478bd9Sstevel@tonic-gate	movl	%esp, %ebp
22277c478bd9Sstevel@tonic-gate	pushl	$.copyinstr_panic_msg
22287c478bd9Sstevel@tonic-gate	call	panic
22297c478bd9Sstevel@tonic-gate1:
22307c478bd9Sstevel@tonic-gate#endif
22317c478bd9Sstevel@tonic-gate	lea	_copyinstr_error, %eax
22327c478bd9Sstevel@tonic-gate	cmpl	%ecx, ARG_UADDR(%esp)	/* test uaddr < kernelbase */
22337c478bd9Sstevel@tonic-gate	jb	do_copystr
22347c478bd9Sstevel@tonic-gate	movl	%gs:CPU_THREAD, %edx
22357c478bd9Sstevel@tonic-gate	jmp	3f
22367c478bd9Sstevel@tonic-gate
22377c478bd9Sstevel@tonic-gate_copyinstr_error:
22387c478bd9Sstevel@tonic-gate	popl	%edi
22397c478bd9Sstevel@tonic-gate	movl	%gs:CPU_THREAD, %edx
22407c478bd9Sstevel@tonic-gate	movl	%edi, T_LOFAULT(%edx)	/* original lofault */
22417c478bd9Sstevel@tonic-gate
22427c478bd9Sstevel@tonic-gate	popl	%edi
22437c478bd9Sstevel@tonic-gate	popl	%ebx
22447c478bd9Sstevel@tonic-gate	popl	%ebp
22457c478bd9Sstevel@tonic-gate3:
22467c478bd9Sstevel@tonic-gate	movl	T_COPYOPS(%edx), %eax
22477c478bd9Sstevel@tonic-gate	cmpl	$0, %eax
22487c478bd9Sstevel@tonic-gate	jz	2f
22497c478bd9Sstevel@tonic-gate	jmp	*CP_COPYINSTR(%eax)
22507c478bd9Sstevel@tonic-gate
22517c478bd9Sstevel@tonic-gate2:	movl	$EFAULT, %eax		/* return EFAULT */
22527c478bd9Sstevel@tonic-gate	ret
22537c478bd9Sstevel@tonic-gate	SET_SIZE(copyinstr)
22547c478bd9Sstevel@tonic-gate
22557c478bd9Sstevel@tonic-gate#undef	ARG_UADDR
22567c478bd9Sstevel@tonic-gate#undef	ARG_KADDR
22577c478bd9Sstevel@tonic-gate
22587c478bd9Sstevel@tonic-gate#endif	/* __i386 */
22597c478bd9Sstevel@tonic-gate#endif	/* __lint */
22607c478bd9Sstevel@tonic-gate
22617c478bd9Sstevel@tonic-gate/*
22627c478bd9Sstevel@tonic-gate * Copy a null terminated string from the kernel
22637c478bd9Sstevel@tonic-gate * address space to the user address space.
22647c478bd9Sstevel@tonic-gate */
22657c478bd9Sstevel@tonic-gate
22667c478bd9Sstevel@tonic-gate#if defined(__lint)
22677c478bd9Sstevel@tonic-gate
22687c478bd9Sstevel@tonic-gate/* ARGSUSED */
22697c478bd9Sstevel@tonic-gateint
22707c478bd9Sstevel@tonic-gatecopyoutstr(const char *kaddr, char *uaddr, size_t maxlength,
22717c478bd9Sstevel@tonic-gate    size_t *lencopied)
22727c478bd9Sstevel@tonic-gate{ return (0); }
22737c478bd9Sstevel@tonic-gate
22747c478bd9Sstevel@tonic-gate#else	/* __lint */
22757c478bd9Sstevel@tonic-gate
22767c478bd9Sstevel@tonic-gate#if defined(__amd64)
22777c478bd9Sstevel@tonic-gate
22787c478bd9Sstevel@tonic-gate	ENTRY(copyoutstr)
22797c478bd9Sstevel@tonic-gate	pushq	%rbp
22807c478bd9Sstevel@tonic-gate	movq	%rsp, %rbp
22817c478bd9Sstevel@tonic-gate	subq	$32, %rsp
22827c478bd9Sstevel@tonic-gate
22837c478bd9Sstevel@tonic-gate	/*
22847c478bd9Sstevel@tonic-gate	 * save args in case we trap and need to rerun as a copyop
22857c478bd9Sstevel@tonic-gate	 */
22867c478bd9Sstevel@tonic-gate	movq	%rdi, (%rsp)
22877c478bd9Sstevel@tonic-gate	movq	%rsi, 0x8(%rsp)
22887c478bd9Sstevel@tonic-gate	movq	%rdx, 0x10(%rsp)
22897c478bd9Sstevel@tonic-gate	movq	%rcx, 0x18(%rsp)
22907c478bd9Sstevel@tonic-gate
22917c478bd9Sstevel@tonic-gate	movq	kernelbase(%rip), %rax
22927c478bd9Sstevel@tonic-gate#ifdef DEBUG
22937c478bd9Sstevel@tonic-gate	cmpq	%rax, %rdi		/* %rdi = kaddr */
22947c478bd9Sstevel@tonic-gate	jnb	1f
22957c478bd9Sstevel@tonic-gate	leaq	.copyoutstr_panic_msg(%rip), %rdi
22967c478bd9Sstevel@tonic-gate	jmp	call_panic		/* setup stack and call panic */
22977c478bd9Sstevel@tonic-gate1:
22987c478bd9Sstevel@tonic-gate#endif
22997c478bd9Sstevel@tonic-gate	/*
23007c478bd9Sstevel@tonic-gate	 * pass lofault value as 5th argument to do_copystr
23017c478bd9Sstevel@tonic-gate	 */
23027c478bd9Sstevel@tonic-gate	leaq	_copyoutstr_error(%rip), %r8
23037c478bd9Sstevel@tonic-gate
23047c478bd9Sstevel@tonic-gate	cmpq	%rax, %rsi		/* test uaddr < kernelbase */
23057c478bd9Sstevel@tonic-gate	jb	do_copystr
23067c478bd9Sstevel@tonic-gate	movq	%gs:CPU_THREAD, %r9
23077c478bd9Sstevel@tonic-gate	jmp	3f
23087c478bd9Sstevel@tonic-gate
23097c478bd9Sstevel@tonic-gate_copyoutstr_error:
23107c478bd9Sstevel@tonic-gate	movq	%r11, T_LOFAULT(%r9)	/* restore the original lofault */
23117c478bd9Sstevel@tonic-gate3:
23127c478bd9Sstevel@tonic-gate	movq	T_COPYOPS(%r9), %rax
23137c478bd9Sstevel@tonic-gate	cmpq	$0, %rax
23147c478bd9Sstevel@tonic-gate	jz	2f
23157c478bd9Sstevel@tonic-gate
23167c478bd9Sstevel@tonic-gate	/*
23177c478bd9Sstevel@tonic-gate	 * reload args for the copyop
23187c478bd9Sstevel@tonic-gate	 */
23197c478bd9Sstevel@tonic-gate	movq	(%rsp), %rdi
23207c478bd9Sstevel@tonic-gate	movq	0x8(%rsp), %rsi
23217c478bd9Sstevel@tonic-gate	movq	0x10(%rsp), %rdx
23227c478bd9Sstevel@tonic-gate	movq	0x18(%rsp), %rcx
23237c478bd9Sstevel@tonic-gate	leave
23247c478bd9Sstevel@tonic-gate	jmp	*CP_COPYOUTSTR(%rax)
23257c478bd9Sstevel@tonic-gate
23267c478bd9Sstevel@tonic-gate2:	movl	$EFAULT, %eax		/* return EFAULT */
23277c478bd9Sstevel@tonic-gate	leave
23287c478bd9Sstevel@tonic-gate	ret
23297c478bd9Sstevel@tonic-gate	SET_SIZE(copyoutstr)
23307c478bd9Sstevel@tonic-gate
23317c478bd9Sstevel@tonic-gate#elif defined(__i386)
23327c478bd9Sstevel@tonic-gate
23337c478bd9Sstevel@tonic-gate#define	ARG_KADDR	4
23347c478bd9Sstevel@tonic-gate#define	ARG_UADDR	8
23357c478bd9Sstevel@tonic-gate
23367c478bd9Sstevel@tonic-gate	ENTRY(copyoutstr)
23377c478bd9Sstevel@tonic-gate	movl	kernelbase, %ecx
23387c478bd9Sstevel@tonic-gate#ifdef DEBUG
23397c478bd9Sstevel@tonic-gate	cmpl	%ecx, ARG_KADDR(%esp)
23407c478bd9Sstevel@tonic-gate	jnb	1f
23417c478bd9Sstevel@tonic-gate	pushl	%ebp
23427c478bd9Sstevel@tonic-gate	movl	%esp, %ebp
23437c478bd9Sstevel@tonic-gate	pushl	$.copyoutstr_panic_msg
23447c478bd9Sstevel@tonic-gate	call	panic
23457c478bd9Sstevel@tonic-gate1:
23467c478bd9Sstevel@tonic-gate#endif
23477c478bd9Sstevel@tonic-gate	lea	_copyoutstr_error, %eax
23487c478bd9Sstevel@tonic-gate	cmpl	%ecx, ARG_UADDR(%esp)	/* test uaddr < kernelbase */
23497c478bd9Sstevel@tonic-gate	jb	do_copystr
23507c478bd9Sstevel@tonic-gate	movl	%gs:CPU_THREAD, %edx
23517c478bd9Sstevel@tonic-gate	jmp	3f
23527c478bd9Sstevel@tonic-gate
23537c478bd9Sstevel@tonic-gate_copyoutstr_error:
23547c478bd9Sstevel@tonic-gate	popl	%edi
23557c478bd9Sstevel@tonic-gate	movl	%gs:CPU_THREAD, %edx
23567c478bd9Sstevel@tonic-gate	movl	%edi, T_LOFAULT(%edx)	/* restore the original lofault */
23577c478bd9Sstevel@tonic-gate
23587c478bd9Sstevel@tonic-gate	popl	%edi
23597c478bd9Sstevel@tonic-gate	popl	%ebx
23607c478bd9Sstevel@tonic-gate	popl	%ebp
23617c478bd9Sstevel@tonic-gate3:
23627c478bd9Sstevel@tonic-gate	movl	T_COPYOPS(%edx), %eax
23637c478bd9Sstevel@tonic-gate	cmpl	$0, %eax
23647c478bd9Sstevel@tonic-gate	jz	2f
23657c478bd9Sstevel@tonic-gate	jmp	*CP_COPYOUTSTR(%eax)
23667c478bd9Sstevel@tonic-gate
23677c478bd9Sstevel@tonic-gate2:	movl	$EFAULT, %eax		/* return EFAULT */
23687c478bd9Sstevel@tonic-gate	ret
23697c478bd9Sstevel@tonic-gate	SET_SIZE(copyoutstr)
23707c478bd9Sstevel@tonic-gate
23717c478bd9Sstevel@tonic-gate#undef	ARG_KADDR
23727c478bd9Sstevel@tonic-gate#undef	ARG_UADDR
23737c478bd9Sstevel@tonic-gate
23747c478bd9Sstevel@tonic-gate#endif	/* __i386 */
23757c478bd9Sstevel@tonic-gate#endif	/* __lint */
23767c478bd9Sstevel@tonic-gate
23777c478bd9Sstevel@tonic-gate/*
23787c478bd9Sstevel@tonic-gate * Since all of the fuword() variants are so similar, we have a macro to spit
23797c478bd9Sstevel@tonic-gate * them out.  This allows us to create DTrace-unobservable functions easily.
23807c478bd9Sstevel@tonic-gate */
23817c478bd9Sstevel@tonic-gate
23827c478bd9Sstevel@tonic-gate#if defined(__lint)
23837c478bd9Sstevel@tonic-gate
23847c478bd9Sstevel@tonic-gate#if defined(__amd64)
23857c478bd9Sstevel@tonic-gate
23867c478bd9Sstevel@tonic-gate/* ARGSUSED */
23877c478bd9Sstevel@tonic-gateint
23887c478bd9Sstevel@tonic-gatefuword64(const void *addr, uint64_t *dst)
23897c478bd9Sstevel@tonic-gate{ return (0); }
23907c478bd9Sstevel@tonic-gate
23917c478bd9Sstevel@tonic-gate#endif
23927c478bd9Sstevel@tonic-gate
23937c478bd9Sstevel@tonic-gate/* ARGSUSED */
23947c478bd9Sstevel@tonic-gateint
23957c478bd9Sstevel@tonic-gatefuword32(const void *addr, uint32_t *dst)
23967c478bd9Sstevel@tonic-gate{ return (0); }
23977c478bd9Sstevel@tonic-gate
23987c478bd9Sstevel@tonic-gate/* ARGSUSED */
23997c478bd9Sstevel@tonic-gateint
24007c478bd9Sstevel@tonic-gatefuword16(const void *addr, uint16_t *dst)
24017c478bd9Sstevel@tonic-gate{ return (0); }
24027c478bd9Sstevel@tonic-gate
24037c478bd9Sstevel@tonic-gate/* ARGSUSED */
24047c478bd9Sstevel@tonic-gateint
24057c478bd9Sstevel@tonic-gatefuword8(const void *addr, uint8_t *dst)
24067c478bd9Sstevel@tonic-gate{ return (0); }
24077c478bd9Sstevel@tonic-gate
24087c478bd9Sstevel@tonic-gate#else	/* __lint */
24097c478bd9Sstevel@tonic-gate
24107c478bd9Sstevel@tonic-gate#if defined(__amd64)
24117c478bd9Sstevel@tonic-gate
24127c478bd9Sstevel@tonic-gate/*
24137c478bd9Sstevel@tonic-gate * (Note that we don't save and reload the arguments here
24147c478bd9Sstevel@tonic-gate * because their values are not altered in the copy path)
24157c478bd9Sstevel@tonic-gate */
24167c478bd9Sstevel@tonic-gate
24177c478bd9Sstevel@tonic-gate#define	FUWORD(NAME, INSTR, REG, COPYOP)	\
24187c478bd9Sstevel@tonic-gate	ENTRY(NAME)				\
24197c478bd9Sstevel@tonic-gate	movq	%gs:CPU_THREAD, %r9;		\
24207c478bd9Sstevel@tonic-gate	cmpq	kernelbase(%rip), %rdi;		\
24217c478bd9Sstevel@tonic-gate	jae	1f;				\
24227c478bd9Sstevel@tonic-gate	leaq	_flt_/**/NAME, %rdx;		\
24237c478bd9Sstevel@tonic-gate	movq	%rdx, T_LOFAULT(%r9);		\
24247c478bd9Sstevel@tonic-gate	INSTR	(%rdi), REG;			\
24257c478bd9Sstevel@tonic-gate	movq	$0, T_LOFAULT(%r9);		\
24267c478bd9Sstevel@tonic-gate	INSTR	REG, (%rsi);			\
24277c478bd9Sstevel@tonic-gate	xorl	%eax, %eax;			\
24287c478bd9Sstevel@tonic-gate	ret;					\
24297c478bd9Sstevel@tonic-gate_flt_/**/NAME:					\
24307c478bd9Sstevel@tonic-gate	movq	$0, T_LOFAULT(%r9);		\
24317c478bd9Sstevel@tonic-gate1:						\
24327c478bd9Sstevel@tonic-gate	movq	T_COPYOPS(%r9), %rax;		\
24337c478bd9Sstevel@tonic-gate	cmpq	$0, %rax;			\
24347c478bd9Sstevel@tonic-gate	jz	2f;				\
24357c478bd9Sstevel@tonic-gate	jmp	*COPYOP(%rax);			\
24367c478bd9Sstevel@tonic-gate2:						\
24377c478bd9Sstevel@tonic-gate	movl	$-1, %eax;			\
24387c478bd9Sstevel@tonic-gate	ret;					\
24397c478bd9Sstevel@tonic-gate	SET_SIZE(NAME)
24407c478bd9Sstevel@tonic-gate
24417c478bd9Sstevel@tonic-gate	FUWORD(fuword64, movq, %rax, CP_FUWORD64)
24427c478bd9Sstevel@tonic-gate	FUWORD(fuword32, movl, %eax, CP_FUWORD32)
24437c478bd9Sstevel@tonic-gate	FUWORD(fuword16, movw, %ax, CP_FUWORD16)
24447c478bd9Sstevel@tonic-gate	FUWORD(fuword8, movb, %al, CP_FUWORD8)
24457c478bd9Sstevel@tonic-gate
24467c478bd9Sstevel@tonic-gate#elif defined(__i386)
24477c478bd9Sstevel@tonic-gate
24487c478bd9Sstevel@tonic-gate#define	FUWORD(NAME, INSTR, REG, COPYOP)	\
24497c478bd9Sstevel@tonic-gate	ENTRY(NAME)				\
24507c478bd9Sstevel@tonic-gate	movl	%gs:CPU_THREAD, %ecx;		\
24517c478bd9Sstevel@tonic-gate	movl	kernelbase, %eax;		\
24527c478bd9Sstevel@tonic-gate	cmpl	%eax, 4(%esp);			\
24537c478bd9Sstevel@tonic-gate	jae	1f;				\
24547c478bd9Sstevel@tonic-gate	lea	_flt_/**/NAME, %edx;		\
24557c478bd9Sstevel@tonic-gate	movl	%edx, T_LOFAULT(%ecx);		\
24567c478bd9Sstevel@tonic-gate	movl	4(%esp), %eax;			\
24577c478bd9Sstevel@tonic-gate	movl	8(%esp), %edx;			\
24587c478bd9Sstevel@tonic-gate	INSTR	(%eax), REG;			\
24597c478bd9Sstevel@tonic-gate	movl	$0, T_LOFAULT(%ecx);		\
24607c478bd9Sstevel@tonic-gate	INSTR	REG, (%edx);			\
24617c478bd9Sstevel@tonic-gate	xorl	%eax, %eax;			\
24627c478bd9Sstevel@tonic-gate	ret;					\
24637c478bd9Sstevel@tonic-gate_flt_/**/NAME:					\
24647c478bd9Sstevel@tonic-gate	movl	$0, T_LOFAULT(%ecx);		\
24657c478bd9Sstevel@tonic-gate1:						\
24667c478bd9Sstevel@tonic-gate	movl	T_COPYOPS(%ecx), %eax;		\
24677c478bd9Sstevel@tonic-gate	cmpl	$0, %eax;			\
24687c478bd9Sstevel@tonic-gate	jz	2f;				\
24697c478bd9Sstevel@tonic-gate	jmp	*COPYOP(%eax);			\
24707c478bd9Sstevel@tonic-gate2:						\
24717c478bd9Sstevel@tonic-gate	movl	$-1, %eax;			\
24727c478bd9Sstevel@tonic-gate	ret;					\
24737c478bd9Sstevel@tonic-gate	SET_SIZE(NAME)
24747c478bd9Sstevel@tonic-gate
24757c478bd9Sstevel@tonic-gate	FUWORD(fuword32, movl, %eax, CP_FUWORD32)
24767c478bd9Sstevel@tonic-gate	FUWORD(fuword16, movw, %ax, CP_FUWORD16)
24777c478bd9Sstevel@tonic-gate	FUWORD(fuword8, movb, %al, CP_FUWORD8)
24787c478bd9Sstevel@tonic-gate
24797c478bd9Sstevel@tonic-gate#endif	/* __i386 */
24807c478bd9Sstevel@tonic-gate
24817c478bd9Sstevel@tonic-gate#undef	FUWORD
24827c478bd9Sstevel@tonic-gate
24837c478bd9Sstevel@tonic-gate#endif	/* __lint */
24847c478bd9Sstevel@tonic-gate
24857c478bd9Sstevel@tonic-gate/*
24867c478bd9Sstevel@tonic-gate * Set user word.
24877c478bd9Sstevel@tonic-gate */
24887c478bd9Sstevel@tonic-gate
24897c478bd9Sstevel@tonic-gate#if defined(__lint)
24907c478bd9Sstevel@tonic-gate
24917c478bd9Sstevel@tonic-gate#if defined(__amd64)
24927c478bd9Sstevel@tonic-gate
24937c478bd9Sstevel@tonic-gate/* ARGSUSED */
24947c478bd9Sstevel@tonic-gateint
24957c478bd9Sstevel@tonic-gatesuword64(void *addr, uint64_t value)
24967c478bd9Sstevel@tonic-gate{ return (0); }
24977c478bd9Sstevel@tonic-gate
24987c478bd9Sstevel@tonic-gate#endif
24997c478bd9Sstevel@tonic-gate
25007c478bd9Sstevel@tonic-gate/* ARGSUSED */
25017c478bd9Sstevel@tonic-gateint
25027c478bd9Sstevel@tonic-gatesuword32(void *addr, uint32_t value)
25037c478bd9Sstevel@tonic-gate{ return (0); }
25047c478bd9Sstevel@tonic-gate
25057c478bd9Sstevel@tonic-gate/* ARGSUSED */
25067c478bd9Sstevel@tonic-gateint
25077c478bd9Sstevel@tonic-gatesuword16(void *addr, uint16_t value)
25087c478bd9Sstevel@tonic-gate{ return (0); }
25097c478bd9Sstevel@tonic-gate
25107c478bd9Sstevel@tonic-gate/* ARGSUSED */
25117c478bd9Sstevel@tonic-gateint
25127c478bd9Sstevel@tonic-gatesuword8(void *addr, uint8_t value)
25137c478bd9Sstevel@tonic-gate{ return (0); }
25147c478bd9Sstevel@tonic-gate
25157c478bd9Sstevel@tonic-gate#else	/* lint */
25167c478bd9Sstevel@tonic-gate
25177c478bd9Sstevel@tonic-gate#if defined(__amd64)
25187c478bd9Sstevel@tonic-gate
25197c478bd9Sstevel@tonic-gate/*
25207c478bd9Sstevel@tonic-gate * (Note that we don't save and reload the arguments here
25217c478bd9Sstevel@tonic-gate * because their values are not altered in the copy path)
25227c478bd9Sstevel@tonic-gate */
25237c478bd9Sstevel@tonic-gate
25247c478bd9Sstevel@tonic-gate#define	SUWORD(NAME, INSTR, REG, COPYOP)	\
25257c478bd9Sstevel@tonic-gate	ENTRY(NAME)				\
25267c478bd9Sstevel@tonic-gate	movq	%gs:CPU_THREAD, %r9;		\
25277c478bd9Sstevel@tonic-gate	cmpq	kernelbase(%rip), %rdi;		\
25287c478bd9Sstevel@tonic-gate	jae	1f;				\
25297c478bd9Sstevel@tonic-gate	leaq	_flt_/**/NAME, %rdx;		\
25307c478bd9Sstevel@tonic-gate	movq	%rdx, T_LOFAULT(%r9);		\
25317c478bd9Sstevel@tonic-gate	INSTR	REG, (%rdi);			\
25327c478bd9Sstevel@tonic-gate	movq	$0, T_LOFAULT(%r9);		\
25337c478bd9Sstevel@tonic-gate	xorl	%eax, %eax;			\
25347c478bd9Sstevel@tonic-gate	ret;					\
25357c478bd9Sstevel@tonic-gate_flt_/**/NAME:					\
25367c478bd9Sstevel@tonic-gate	movq	$0, T_LOFAULT(%r9);		\
25377c478bd9Sstevel@tonic-gate1:						\
25387c478bd9Sstevel@tonic-gate	movq	T_COPYOPS(%r9), %rax;		\
25397c478bd9Sstevel@tonic-gate	cmpq	$0, %rax;			\
25407c478bd9Sstevel@tonic-gate	jz	3f;				\
25417c478bd9Sstevel@tonic-gate	jmp	*COPYOP(%rax);			\
25427c478bd9Sstevel@tonic-gate3:						\
25437c478bd9Sstevel@tonic-gate	movl	$-1, %eax;			\
25447c478bd9Sstevel@tonic-gate	ret;					\
25457c478bd9Sstevel@tonic-gate	SET_SIZE(NAME)
25467c478bd9Sstevel@tonic-gate
25477c478bd9Sstevel@tonic-gate	SUWORD(suword64, movq, %rsi, CP_SUWORD64)
25487c478bd9Sstevel@tonic-gate	SUWORD(suword32, movl, %esi, CP_SUWORD32)
25497c478bd9Sstevel@tonic-gate	SUWORD(suword16, movw, %si, CP_SUWORD16)
25507c478bd9Sstevel@tonic-gate	SUWORD(suword8, movb, %sil, CP_SUWORD8)
25517c478bd9Sstevel@tonic-gate
25527c478bd9Sstevel@tonic-gate#elif defined(__i386)
25537c478bd9Sstevel@tonic-gate
25547c478bd9Sstevel@tonic-gate#define	SUWORD(NAME, INSTR, REG, COPYOP)	\
25557c478bd9Sstevel@tonic-gate	ENTRY(NAME)				\
25567c478bd9Sstevel@tonic-gate	movl	%gs:CPU_THREAD, %ecx;		\
25577c478bd9Sstevel@tonic-gate	movl	kernelbase, %eax;		\
25587c478bd9Sstevel@tonic-gate	cmpl	%eax, 4(%esp);			\
25597c478bd9Sstevel@tonic-gate	jae	1f;				\
25607c478bd9Sstevel@tonic-gate	lea	_flt_/**/NAME, %edx;		\
25617c478bd9Sstevel@tonic-gate	movl	%edx, T_LOFAULT(%ecx);		\
25627c478bd9Sstevel@tonic-gate	movl	4(%esp), %eax;			\
25637c478bd9Sstevel@tonic-gate	movl	8(%esp), %edx;			\
25647c478bd9Sstevel@tonic-gate	INSTR	REG, (%eax);			\
25657c478bd9Sstevel@tonic-gate	movl	$0, T_LOFAULT(%ecx);		\
25667c478bd9Sstevel@tonic-gate	xorl	%eax, %eax;			\
25677c478bd9Sstevel@tonic-gate	ret;					\
25687c478bd9Sstevel@tonic-gate_flt_/**/NAME:					\
25697c478bd9Sstevel@tonic-gate	movl	$0, T_LOFAULT(%ecx);		\
25707c478bd9Sstevel@tonic-gate1:						\
25717c478bd9Sstevel@tonic-gate	movl	T_COPYOPS(%ecx), %eax;		\
25727c478bd9Sstevel@tonic-gate	cmpl	$0, %eax;			\
25737c478bd9Sstevel@tonic-gate	jz	3f;				\
25747c478bd9Sstevel@tonic-gate	movl	COPYOP(%eax), %ecx;		\
25757c478bd9Sstevel@tonic-gate	jmp	*%ecx;				\
25767c478bd9Sstevel@tonic-gate3:						\
25777c478bd9Sstevel@tonic-gate	movl	$-1, %eax;			\
25787c478bd9Sstevel@tonic-gate	ret;					\
25797c478bd9Sstevel@tonic-gate	SET_SIZE(NAME)
25807c478bd9Sstevel@tonic-gate
25817c478bd9Sstevel@tonic-gate	SUWORD(suword32, movl, %edx, CP_SUWORD32)
25827c478bd9Sstevel@tonic-gate	SUWORD(suword16, movw, %dx, CP_SUWORD16)
25837c478bd9Sstevel@tonic-gate	SUWORD(suword8, movb, %dl, CP_SUWORD8)
25847c478bd9Sstevel@tonic-gate
25857c478bd9Sstevel@tonic-gate#endif	/* __i386 */
25867c478bd9Sstevel@tonic-gate
25877c478bd9Sstevel@tonic-gate#undef	SUWORD
25887c478bd9Sstevel@tonic-gate
25897c478bd9Sstevel@tonic-gate#endif	/* __lint */
25907c478bd9Sstevel@tonic-gate
25917c478bd9Sstevel@tonic-gate#if defined(__lint)
25927c478bd9Sstevel@tonic-gate
25937c478bd9Sstevel@tonic-gate#if defined(__amd64)
25947c478bd9Sstevel@tonic-gate
25957c478bd9Sstevel@tonic-gate/*ARGSUSED*/
25967c478bd9Sstevel@tonic-gatevoid
25977c478bd9Sstevel@tonic-gatefuword64_noerr(const void *addr, uint64_t *dst)
25987c478bd9Sstevel@tonic-gate{}
25997c478bd9Sstevel@tonic-gate
26007c478bd9Sstevel@tonic-gate#endif
26017c478bd9Sstevel@tonic-gate
26027c478bd9Sstevel@tonic-gate/*ARGSUSED*/
26037c478bd9Sstevel@tonic-gatevoid
26047c478bd9Sstevel@tonic-gatefuword32_noerr(const void *addr, uint32_t *dst)
26057c478bd9Sstevel@tonic-gate{}
26067c478bd9Sstevel@tonic-gate
26077c478bd9Sstevel@tonic-gate/*ARGSUSED*/
26087c478bd9Sstevel@tonic-gatevoid
26097c478bd9Sstevel@tonic-gatefuword8_noerr(const void *addr, uint8_t *dst)
26107c478bd9Sstevel@tonic-gate{}
26117c478bd9Sstevel@tonic-gate
26127c478bd9Sstevel@tonic-gate/*ARGSUSED*/
26137c478bd9Sstevel@tonic-gatevoid
26147c478bd9Sstevel@tonic-gatefuword16_noerr(const void *addr, uint16_t *dst)
26157c478bd9Sstevel@tonic-gate{}
26167c478bd9Sstevel@tonic-gate
26177c478bd9Sstevel@tonic-gate#else   /* __lint */
26187c478bd9Sstevel@tonic-gate
26197c478bd9Sstevel@tonic-gate#if defined(__amd64)
26207c478bd9Sstevel@tonic-gate
26217c478bd9Sstevel@tonic-gate#define	FUWORD_NOERR(NAME, INSTR, REG)		\
26227c478bd9Sstevel@tonic-gate	ENTRY(NAME)				\
26237c478bd9Sstevel@tonic-gate	cmpq	kernelbase(%rip), %rdi;		\
26247c478bd9Sstevel@tonic-gate	cmovnbq	kernelbase(%rip), %rdi;		\
26257c478bd9Sstevel@tonic-gate	INSTR	(%rdi), REG;			\
26267c478bd9Sstevel@tonic-gate	INSTR	REG, (%rsi);			\
26277c478bd9Sstevel@tonic-gate	ret;					\
26287c478bd9Sstevel@tonic-gate	SET_SIZE(NAME)
26297c478bd9Sstevel@tonic-gate
26307c478bd9Sstevel@tonic-gate	FUWORD_NOERR(fuword64_noerr, movq, %rax)
26317c478bd9Sstevel@tonic-gate	FUWORD_NOERR(fuword32_noerr, movl, %eax)
26327c478bd9Sstevel@tonic-gate	FUWORD_NOERR(fuword16_noerr, movw, %ax)
26337c478bd9Sstevel@tonic-gate	FUWORD_NOERR(fuword8_noerr, movb, %al)
26347c478bd9Sstevel@tonic-gate
26357c478bd9Sstevel@tonic-gate#elif defined(__i386)
26367c478bd9Sstevel@tonic-gate
26377c478bd9Sstevel@tonic-gate#define	FUWORD_NOERR(NAME, INSTR, REG)		\
26387c478bd9Sstevel@tonic-gate	ENTRY(NAME)				\
26397c478bd9Sstevel@tonic-gate	movl	4(%esp), %eax;			\
26407c478bd9Sstevel@tonic-gate	cmpl	kernelbase, %eax;		\
26417c478bd9Sstevel@tonic-gate	jb	1f;				\
26427c478bd9Sstevel@tonic-gate	movl	kernelbase, %eax;		\
26437c478bd9Sstevel@tonic-gate1:	movl	8(%esp), %edx;			\
26447c478bd9Sstevel@tonic-gate	INSTR	(%eax), REG;			\
26457c478bd9Sstevel@tonic-gate	INSTR	REG, (%edx);			\
26467c478bd9Sstevel@tonic-gate	ret;					\
26477c478bd9Sstevel@tonic-gate	SET_SIZE(NAME)
26487c478bd9Sstevel@tonic-gate
26497c478bd9Sstevel@tonic-gate	FUWORD_NOERR(fuword32_noerr, movl, %ecx)
26507c478bd9Sstevel@tonic-gate	FUWORD_NOERR(fuword16_noerr, movw, %cx)
26517c478bd9Sstevel@tonic-gate	FUWORD_NOERR(fuword8_noerr, movb, %cl)
26527c478bd9Sstevel@tonic-gate
26537c478bd9Sstevel@tonic-gate#endif	/* __i386 */
26547c478bd9Sstevel@tonic-gate
26557c478bd9Sstevel@tonic-gate#undef	FUWORD_NOERR
26567c478bd9Sstevel@tonic-gate
26577c478bd9Sstevel@tonic-gate#endif	/* __lint */
26587c478bd9Sstevel@tonic-gate
26597c478bd9Sstevel@tonic-gate#if defined(__lint)
26607c478bd9Sstevel@tonic-gate
26617c478bd9Sstevel@tonic-gate#if defined(__amd64)
26627c478bd9Sstevel@tonic-gate
26637c478bd9Sstevel@tonic-gate/*ARGSUSED*/
26647c478bd9Sstevel@tonic-gatevoid
26657c478bd9Sstevel@tonic-gatesuword64_noerr(void *addr, uint64_t value)
26667c478bd9Sstevel@tonic-gate{}
26677c478bd9Sstevel@tonic-gate
26687c478bd9Sstevel@tonic-gate#endif
26697c478bd9Sstevel@tonic-gate
26707c478bd9Sstevel@tonic-gate/*ARGSUSED*/
26717c478bd9Sstevel@tonic-gatevoid
26727c478bd9Sstevel@tonic-gatesuword32_noerr(void *addr, uint32_t value)
26737c478bd9Sstevel@tonic-gate{}
26747c478bd9Sstevel@tonic-gate
26757c478bd9Sstevel@tonic-gate/*ARGSUSED*/
26767c478bd9Sstevel@tonic-gatevoid
26777c478bd9Sstevel@tonic-gatesuword16_noerr(void *addr, uint16_t value)
26787c478bd9Sstevel@tonic-gate{}
26797c478bd9Sstevel@tonic-gate
26807c478bd9Sstevel@tonic-gate/*ARGSUSED*/
26817c478bd9Sstevel@tonic-gatevoid
26827c478bd9Sstevel@tonic-gatesuword8_noerr(void *addr, uint8_t value)
26837c478bd9Sstevel@tonic-gate{}
26847c478bd9Sstevel@tonic-gate
26857c478bd9Sstevel@tonic-gate#else	/* lint */
26867c478bd9Sstevel@tonic-gate
26877c478bd9Sstevel@tonic-gate#if defined(__amd64)
26887c478bd9Sstevel@tonic-gate
26897c478bd9Sstevel@tonic-gate#define	SUWORD_NOERR(NAME, INSTR, REG)		\
26907c478bd9Sstevel@tonic-gate	ENTRY(NAME)				\
26917c478bd9Sstevel@tonic-gate	cmpq	kernelbase(%rip), %rdi;		\
26927c478bd9Sstevel@tonic-gate	cmovnbq	kernelbase(%rip), %rdi;		\
26937c478bd9Sstevel@tonic-gate	INSTR	REG, (%rdi);			\
26947c478bd9Sstevel@tonic-gate	ret;					\
26957c478bd9Sstevel@tonic-gate	SET_SIZE(NAME)
26967c478bd9Sstevel@tonic-gate
26977c478bd9Sstevel@tonic-gate	SUWORD_NOERR(suword64_noerr, movq, %rsi)
26987c478bd9Sstevel@tonic-gate	SUWORD_NOERR(suword32_noerr, movl, %esi)
26997c478bd9Sstevel@tonic-gate	SUWORD_NOERR(suword16_noerr, movw, %si)
27007c478bd9Sstevel@tonic-gate	SUWORD_NOERR(suword8_noerr, movb, %sil)
27017c478bd9Sstevel@tonic-gate
27027c478bd9Sstevel@tonic-gate#elif defined(__i386)
27037c478bd9Sstevel@tonic-gate
27047c478bd9Sstevel@tonic-gate#define	SUWORD_NOERR(NAME, INSTR, REG)		\
27057c478bd9Sstevel@tonic-gate	ENTRY(NAME)				\
27067c478bd9Sstevel@tonic-gate	movl	4(%esp), %eax;			\
27077c478bd9Sstevel@tonic-gate	cmpl	kernelbase, %eax;		\
27087c478bd9Sstevel@tonic-gate	jb	1f;				\
27097c478bd9Sstevel@tonic-gate	movl	kernelbase, %eax;		\
27107c478bd9Sstevel@tonic-gate1:						\
27117c478bd9Sstevel@tonic-gate	movl	8(%esp), %edx;			\
27127c478bd9Sstevel@tonic-gate	INSTR	REG, (%eax);			\
27137c478bd9Sstevel@tonic-gate	ret;					\
27147c478bd9Sstevel@tonic-gate	SET_SIZE(NAME)
27157c478bd9Sstevel@tonic-gate
27167c478bd9Sstevel@tonic-gate	SUWORD_NOERR(suword32_noerr, movl, %edx)
27177c478bd9Sstevel@tonic-gate	SUWORD_NOERR(suword16_noerr, movw, %dx)
27187c478bd9Sstevel@tonic-gate	SUWORD_NOERR(suword8_noerr, movb, %dl)
27197c478bd9Sstevel@tonic-gate
27207c478bd9Sstevel@tonic-gate#endif	/* __i386 */
27217c478bd9Sstevel@tonic-gate
27227c478bd9Sstevel@tonic-gate#undef	SUWORD_NOERR
27237c478bd9Sstevel@tonic-gate
27247c478bd9Sstevel@tonic-gate#endif	/* lint */
27257c478bd9Sstevel@tonic-gate
27267c478bd9Sstevel@tonic-gate
27277c478bd9Sstevel@tonic-gate#if defined(__lint)
27287c478bd9Sstevel@tonic-gate
27297c478bd9Sstevel@tonic-gate/*ARGSUSED*/
27307c478bd9Sstevel@tonic-gateint
27317c478bd9Sstevel@tonic-gatesubyte(void *addr, uchar_t value)
27327c478bd9Sstevel@tonic-gate{ return (0); }
27337c478bd9Sstevel@tonic-gate
27347c478bd9Sstevel@tonic-gate/*ARGSUSED*/
27357c478bd9Sstevel@tonic-gatevoid
27367c478bd9Sstevel@tonic-gatesubyte_noerr(void *addr, uchar_t value)
27377c478bd9Sstevel@tonic-gate{}
27387c478bd9Sstevel@tonic-gate
27397c478bd9Sstevel@tonic-gate/*ARGSUSED*/
27407c478bd9Sstevel@tonic-gateint
27417c478bd9Sstevel@tonic-gatefulword(const void *addr, ulong_t *valuep)
27427c478bd9Sstevel@tonic-gate{ return (0); }
27437c478bd9Sstevel@tonic-gate
27447c478bd9Sstevel@tonic-gate/*ARGSUSED*/
27457c478bd9Sstevel@tonic-gatevoid
27467c478bd9Sstevel@tonic-gatefulword_noerr(const void *addr, ulong_t *valuep)
27477c478bd9Sstevel@tonic-gate{}
27487c478bd9Sstevel@tonic-gate
27497c478bd9Sstevel@tonic-gate/*ARGSUSED*/
27507c478bd9Sstevel@tonic-gateint
27517c478bd9Sstevel@tonic-gatesulword(void *addr, ulong_t valuep)
27527c478bd9Sstevel@tonic-gate{ return (0); }
27537c478bd9Sstevel@tonic-gate
27547c478bd9Sstevel@tonic-gate/*ARGSUSED*/
27557c478bd9Sstevel@tonic-gatevoid
27567c478bd9Sstevel@tonic-gatesulword_noerr(void *addr, ulong_t valuep)
27577c478bd9Sstevel@tonic-gate{}
27587c478bd9Sstevel@tonic-gate
27597c478bd9Sstevel@tonic-gate#else
27607c478bd9Sstevel@tonic-gate
27617c478bd9Sstevel@tonic-gate	.weak	subyte
27627c478bd9Sstevel@tonic-gate	subyte=suword8
27637c478bd9Sstevel@tonic-gate	.weak	subyte_noerr
27647c478bd9Sstevel@tonic-gate	subyte_noerr=suword8_noerr
27657c478bd9Sstevel@tonic-gate
27667c478bd9Sstevel@tonic-gate#if defined(__amd64)
27677c478bd9Sstevel@tonic-gate
27687c478bd9Sstevel@tonic-gate	.weak	fulword
27697c478bd9Sstevel@tonic-gate	fulword=fuword64
27707c478bd9Sstevel@tonic-gate	.weak	fulword_noerr
27717c478bd9Sstevel@tonic-gate	fulword_noerr=fuword64_noerr
27727c478bd9Sstevel@tonic-gate	.weak	sulword
27737c478bd9Sstevel@tonic-gate	sulword=suword64
27747c478bd9Sstevel@tonic-gate	.weak	sulword_noerr
27757c478bd9Sstevel@tonic-gate	sulword_noerr=suword64_noerr
27767c478bd9Sstevel@tonic-gate
27777c478bd9Sstevel@tonic-gate#elif defined(__i386)
27787c478bd9Sstevel@tonic-gate
27797c478bd9Sstevel@tonic-gate	.weak	fulword
27807c478bd9Sstevel@tonic-gate	fulword=fuword32
27817c478bd9Sstevel@tonic-gate	.weak	fulword_noerr
27827c478bd9Sstevel@tonic-gate	fulword_noerr=fuword32_noerr
27837c478bd9Sstevel@tonic-gate	.weak	sulword
27847c478bd9Sstevel@tonic-gate	sulword=suword32
27857c478bd9Sstevel@tonic-gate	.weak	sulword_noerr
27867c478bd9Sstevel@tonic-gate	sulword_noerr=suword32_noerr
27877c478bd9Sstevel@tonic-gate
27887c478bd9Sstevel@tonic-gate#endif /* __i386 */
27897c478bd9Sstevel@tonic-gate
27907c478bd9Sstevel@tonic-gate#endif /* __lint */
27917c478bd9Sstevel@tonic-gate
27927c478bd9Sstevel@tonic-gate#if defined(__lint)
27937c478bd9Sstevel@tonic-gate
27947c478bd9Sstevel@tonic-gate/*
27957c478bd9Sstevel@tonic-gate * Copy a block of storage - must not overlap (from + len <= to).
27967c478bd9Sstevel@tonic-gate * No fault handler installed (to be called under on_fault())
27977c478bd9Sstevel@tonic-gate */
27987c478bd9Sstevel@tonic-gate
27997c478bd9Sstevel@tonic-gate/* ARGSUSED */
28007c478bd9Sstevel@tonic-gatevoid
28017c478bd9Sstevel@tonic-gatecopyout_noerr(const void *kfrom, void *uto, size_t count)
28027c478bd9Sstevel@tonic-gate{}
28037c478bd9Sstevel@tonic-gate
28047c478bd9Sstevel@tonic-gate/* ARGSUSED */
28057c478bd9Sstevel@tonic-gatevoid
28067c478bd9Sstevel@tonic-gatecopyin_noerr(const void *ufrom, void *kto, size_t count)
28077c478bd9Sstevel@tonic-gate{}
28087c478bd9Sstevel@tonic-gate
28097c478bd9Sstevel@tonic-gate/*
28107c478bd9Sstevel@tonic-gate * Zero a block of storage in user space
28117c478bd9Sstevel@tonic-gate */
28127c478bd9Sstevel@tonic-gate
28137c478bd9Sstevel@tonic-gate/* ARGSUSED */
28147c478bd9Sstevel@tonic-gatevoid
28157c478bd9Sstevel@tonic-gateuzero(void *addr, size_t count)
28167c478bd9Sstevel@tonic-gate{}
28177c478bd9Sstevel@tonic-gate
28187c478bd9Sstevel@tonic-gate/*
28197c478bd9Sstevel@tonic-gate * copy a block of storage in user space
28207c478bd9Sstevel@tonic-gate */
28217c478bd9Sstevel@tonic-gate
28227c478bd9Sstevel@tonic-gate/* ARGSUSED */
28237c478bd9Sstevel@tonic-gatevoid
28247c478bd9Sstevel@tonic-gateucopy(const void *ufrom, void *uto, size_t ulength)
28257c478bd9Sstevel@tonic-gate{}
28267c478bd9Sstevel@tonic-gate
28279acbbeafSnn35248/*
28289acbbeafSnn35248 * copy a string in user space
28299acbbeafSnn35248 */
28309acbbeafSnn35248
28319acbbeafSnn35248/* ARGSUSED */
28329acbbeafSnn35248void
28339acbbeafSnn35248ucopystr(const char *ufrom, char *uto, size_t umaxlength, size_t *lencopied)
28349acbbeafSnn35248{}
28359acbbeafSnn35248
28367c478bd9Sstevel@tonic-gate#else /* __lint */
28377c478bd9Sstevel@tonic-gate
28387c478bd9Sstevel@tonic-gate#if defined(__amd64)
28397c478bd9Sstevel@tonic-gate
28407c478bd9Sstevel@tonic-gate	ENTRY(copyin_noerr)
28417c478bd9Sstevel@tonic-gate	movq	kernelbase(%rip), %rax
28427c478bd9Sstevel@tonic-gate#ifdef DEBUG
28437c478bd9Sstevel@tonic-gate	cmpq	%rax, %rsi		/* %rsi = kto */
28447c478bd9Sstevel@tonic-gate	jae	1f
28457c478bd9Sstevel@tonic-gate	leaq	.cpyin_ne_pmsg(%rip), %rdi
28467c478bd9Sstevel@tonic-gate	jmp	call_panic		/* setup stack and call panic */
28477c478bd9Sstevel@tonic-gate1:
28487c478bd9Sstevel@tonic-gate#endif
28497c478bd9Sstevel@tonic-gate	cmpq	%rax, %rdi		/* ufrom < kernelbase */
28507c478bd9Sstevel@tonic-gate	jb	do_copy
28517c478bd9Sstevel@tonic-gate	movq	%rax, %rdi		/* force fault at kernelbase */
28527c478bd9Sstevel@tonic-gate	jmp	do_copy
28537c478bd9Sstevel@tonic-gate	SET_SIZE(copyin_noerr)
28547c478bd9Sstevel@tonic-gate
28557c478bd9Sstevel@tonic-gate	ENTRY(copyout_noerr)
28567c478bd9Sstevel@tonic-gate	movq	kernelbase(%rip), %rax
28577c478bd9Sstevel@tonic-gate#ifdef DEBUG
28587c478bd9Sstevel@tonic-gate	cmpq	%rax, %rdi		/* %rdi = kfrom */
28597c478bd9Sstevel@tonic-gate	jae	1f
28607c478bd9Sstevel@tonic-gate	leaq	.cpyout_ne_pmsg(%rip), %rdi
28617c478bd9Sstevel@tonic-gate	jmp	call_panic		/* setup stack and call panic */
28627c478bd9Sstevel@tonic-gate1:
28637c478bd9Sstevel@tonic-gate#endif
28647c478bd9Sstevel@tonic-gate	cmpq	%rax, %rsi		/* uto < kernelbase */
28657c478bd9Sstevel@tonic-gate	jb	do_copy
28667c478bd9Sstevel@tonic-gate	movq	%rax, %rsi		/* force fault at kernelbase */
28677c478bd9Sstevel@tonic-gate	jmp	do_copy
28687c478bd9Sstevel@tonic-gate	SET_SIZE(copyout_noerr)
28697c478bd9Sstevel@tonic-gate
28707c478bd9Sstevel@tonic-gate	ENTRY(uzero)
287140c00cd7Sahl	movq	kernelbase(%rip), %rax
287240c00cd7Sahl	cmpq	%rax, %rdi
287340c00cd7Sahl	jb	do_zero
287440c00cd7Sahl	movq	%rax, %rdi	/* force fault at kernelbase */
28757c478bd9Sstevel@tonic-gate	jmp	do_zero
28767c478bd9Sstevel@tonic-gate	SET_SIZE(uzero)
28777c478bd9Sstevel@tonic-gate
28787c478bd9Sstevel@tonic-gate	ENTRY(ucopy)
28797c478bd9Sstevel@tonic-gate	movq	kernelbase(%rip), %rax
288040c00cd7Sahl	cmpq	%rax, %rdi
28819acbbeafSnn35248	cmovaeq	%rax, %rdi	/* force fault at kernelbase */
288240c00cd7Sahl	cmpq	%rax, %rsi
28839acbbeafSnn35248	cmovaeq	%rax, %rsi	/* force fault at kernelbase */
28847c478bd9Sstevel@tonic-gate	jmp	do_copy
28857c478bd9Sstevel@tonic-gate	SET_SIZE(ucopy)
28867c478bd9Sstevel@tonic-gate
28879acbbeafSnn35248	ENTRY(ucopystr)
288887131306SRobert Mustacchi	pushq	%rbp
288987131306SRobert Mustacchi	movq	%rsp, %rbp
28909acbbeafSnn35248	movq	kernelbase(%rip), %rax
28919acbbeafSnn35248	cmpq	%rax, %rdi
28929acbbeafSnn35248	cmovaeq	%rax, %rdi	/* force fault at kernelbase */
28939acbbeafSnn35248	cmpq	%rax, %rsi
28949acbbeafSnn35248	cmovaeq	%rax, %rsi	/* force fault at kernelbase */
28959acbbeafSnn35248	/* do_copystr expects lofault address in %r8 */
28969acbbeafSnn35248	movq	%gs:CPU_THREAD, %r8
28979acbbeafSnn35248	movq	T_LOFAULT(%r8), %r8
28989acbbeafSnn35248	jmp	do_copystr
28999acbbeafSnn35248	SET_SIZE(ucopystr)
29009acbbeafSnn35248
29017c478bd9Sstevel@tonic-gate#elif defined(__i386)
29027c478bd9Sstevel@tonic-gate
29037c478bd9Sstevel@tonic-gate	ENTRY(copyin_noerr)
29047c478bd9Sstevel@tonic-gate	movl	kernelbase, %eax
29057c478bd9Sstevel@tonic-gate#ifdef DEBUG
29067c478bd9Sstevel@tonic-gate	cmpl	%eax, 8(%esp)
29077c478bd9Sstevel@tonic-gate	jae	1f
29087c478bd9Sstevel@tonic-gate	pushl	$.cpyin_ne_pmsg
29097c478bd9Sstevel@tonic-gate	call	panic
29107c478bd9Sstevel@tonic-gate1:
29117c478bd9Sstevel@tonic-gate#endif
29127c478bd9Sstevel@tonic-gate	cmpl	%eax, 4(%esp)
29137c478bd9Sstevel@tonic-gate	jb	do_copy
29147c478bd9Sstevel@tonic-gate	movl	%eax, 4(%esp)	/* force fault at kernelbase */
29157c478bd9Sstevel@tonic-gate	jmp	do_copy
29167c478bd9Sstevel@tonic-gate	SET_SIZE(copyin_noerr)
29177c478bd9Sstevel@tonic-gate
29187c478bd9Sstevel@tonic-gate	ENTRY(copyout_noerr)
29197c478bd9Sstevel@tonic-gate	movl	kernelbase, %eax
29207c478bd9Sstevel@tonic-gate#ifdef DEBUG
29217c478bd9Sstevel@tonic-gate	cmpl	%eax, 4(%esp)
29227c478bd9Sstevel@tonic-gate	jae	1f
29237c478bd9Sstevel@tonic-gate	pushl	$.cpyout_ne_pmsg
29247c478bd9Sstevel@tonic-gate	call	panic
29257c478bd9Sstevel@tonic-gate1:
29267c478bd9Sstevel@tonic-gate#endif
29277c478bd9Sstevel@tonic-gate	cmpl	%eax, 8(%esp)
29287c478bd9Sstevel@tonic-gate	jb	do_copy
29297c478bd9Sstevel@tonic-gate	movl	%eax, 8(%esp)	/* force fault at kernelbase */
29307c478bd9Sstevel@tonic-gate	jmp	do_copy
29317c478bd9Sstevel@tonic-gate	SET_SIZE(copyout_noerr)
29327c478bd9Sstevel@tonic-gate
29337c478bd9Sstevel@tonic-gate	ENTRY(uzero)
29347c478bd9Sstevel@tonic-gate	movl	kernelbase, %eax
29357c478bd9Sstevel@tonic-gate	cmpl	%eax, 4(%esp)
293640c00cd7Sahl	jb	do_zero
293740c00cd7Sahl	movl	%eax, 4(%esp)	/* force fault at kernelbase */
29387c478bd9Sstevel@tonic-gate	jmp	do_zero
29397c478bd9Sstevel@tonic-gate	SET_SIZE(uzero)
29407c478bd9Sstevel@tonic-gate
29417c478bd9Sstevel@tonic-gate	ENTRY(ucopy)
29427c478bd9Sstevel@tonic-gate	movl	kernelbase, %eax
29437c478bd9Sstevel@tonic-gate	cmpl	%eax, 4(%esp)
29447c478bd9Sstevel@tonic-gate	jb	1f
294540c00cd7Sahl	movl	%eax, 4(%esp)	/* force fault at kernelbase */
29467c478bd9Sstevel@tonic-gate1:
294740c00cd7Sahl	cmpl	%eax, 8(%esp)
294840c00cd7Sahl	jb	do_copy
294940c00cd7Sahl	movl	%eax, 8(%esp)	/* force fault at kernelbase */
29507c478bd9Sstevel@tonic-gate	jmp	do_copy
29517c478bd9Sstevel@tonic-gate	SET_SIZE(ucopy)
29527c478bd9Sstevel@tonic-gate
29539acbbeafSnn35248	ENTRY(ucopystr)
29549acbbeafSnn35248	movl	kernelbase, %eax
29559acbbeafSnn35248	cmpl	%eax, 4(%esp)
29569acbbeafSnn35248	jb	1f
29579acbbeafSnn35248	movl	%eax, 4(%esp)	/* force fault at kernelbase */
29589acbbeafSnn352481:
29599acbbeafSnn35248	cmpl	%eax, 8(%esp)
29609acbbeafSnn35248	jb	2f
29619acbbeafSnn35248	movl	%eax, 8(%esp)	/* force fault at kernelbase */
29629acbbeafSnn352482:
29639acbbeafSnn35248	/* do_copystr expects the lofault address in %eax */
29649acbbeafSnn35248	movl	%gs:CPU_THREAD, %eax
29659acbbeafSnn35248	movl	T_LOFAULT(%eax), %eax
29669acbbeafSnn35248	jmp	do_copystr
29679acbbeafSnn35248	SET_SIZE(ucopystr)
29689acbbeafSnn35248
29697c478bd9Sstevel@tonic-gate#endif	/* __i386 */
29707c478bd9Sstevel@tonic-gate
29717c478bd9Sstevel@tonic-gate#ifdef DEBUG
29727c478bd9Sstevel@tonic-gate	.data
29737c478bd9Sstevel@tonic-gate.kcopy_panic_msg:
29747c478bd9Sstevel@tonic-gate	.string "kcopy: arguments below kernelbase"
29757c478bd9Sstevel@tonic-gate.bcopy_panic_msg:
29767c478bd9Sstevel@tonic-gate	.string "bcopy: arguments below kernelbase"
29777c478bd9Sstevel@tonic-gate.kzero_panic_msg:
29787c478bd9Sstevel@tonic-gate        .string "kzero: arguments below kernelbase"
29797c478bd9Sstevel@tonic-gate.bzero_panic_msg:
29807c478bd9Sstevel@tonic-gate	.string	"bzero: arguments below kernelbase"
29817c478bd9Sstevel@tonic-gate.copyin_panic_msg:
29827c478bd9Sstevel@tonic-gate	.string "copyin: kaddr argument below kernelbase"
29837c478bd9Sstevel@tonic-gate.xcopyin_panic_msg:
29847c478bd9Sstevel@tonic-gate	.string	"xcopyin: kaddr argument below kernelbase"
29857c478bd9Sstevel@tonic-gate.copyout_panic_msg:
29867c478bd9Sstevel@tonic-gate	.string "copyout: kaddr argument below kernelbase"
29877c478bd9Sstevel@tonic-gate.xcopyout_panic_msg:
29887c478bd9Sstevel@tonic-gate	.string	"xcopyout: kaddr argument below kernelbase"
29897c478bd9Sstevel@tonic-gate.copystr_panic_msg:
29907c478bd9Sstevel@tonic-gate	.string	"copystr: arguments in user space"
29917c478bd9Sstevel@tonic-gate.copyinstr_panic_msg:
29927c478bd9Sstevel@tonic-gate	.string	"copyinstr: kaddr argument not in kernel address space"
29937c478bd9Sstevel@tonic-gate.copyoutstr_panic_msg:
29947c478bd9Sstevel@tonic-gate	.string	"copyoutstr: kaddr argument not in kernel address space"
29957c478bd9Sstevel@tonic-gate.cpyin_ne_pmsg:
29967c478bd9Sstevel@tonic-gate	.string "copyin_noerr: argument not in kernel address space"
29977c478bd9Sstevel@tonic-gate.cpyout_ne_pmsg:
29987c478bd9Sstevel@tonic-gate	.string "copyout_noerr: argument not in kernel address space"
29997c478bd9Sstevel@tonic-gate#endif
30007c478bd9Sstevel@tonic-gate
30017c478bd9Sstevel@tonic-gate#endif	/* __lint */
3002