xref: /onnv-gate/usr/src/uts/intel/ia32/ml/i86_subr.s (revision 13134:8315ff49e22e)
10Sstevel@tonic-gate/*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
51582Skchow * Common Development and Distribution License (the "License").
61582Skchow * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
213446Smrj
220Sstevel@tonic-gate/*
2312826Skuriakose.kuruvilla@oracle.com * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate/*
270Sstevel@tonic-gate *  Copyright (c) 1990, 1991 UNIX System Laboratories, Inc.
280Sstevel@tonic-gate *  Copyright (c) 1984, 1986, 1987, 1988, 1989, 1990 AT&T
290Sstevel@tonic-gate *    All Rights Reserved
300Sstevel@tonic-gate */
310Sstevel@tonic-gate
320Sstevel@tonic-gate/*
33*13134Skuriakose.kuruvilla@oracle.com * Copyright (c) 2009, Intel Corporation.
34*13134Skuriakose.kuruvilla@oracle.com * All rights reserved.
35*13134Skuriakose.kuruvilla@oracle.com */
36*13134Skuriakose.kuruvilla@oracle.com
37*13134Skuriakose.kuruvilla@oracle.com/*
380Sstevel@tonic-gate * General assembly language routines.
390Sstevel@tonic-gate * It is the intent of this file to contain routines that are
400Sstevel@tonic-gate * independent of the specific kernel architecture, and those that are
410Sstevel@tonic-gate * common across kernel architectures.
420Sstevel@tonic-gate * As architectures diverge, and implementations of specific
430Sstevel@tonic-gate * architecture-dependent routines change, the routines should be moved
440Sstevel@tonic-gate * from this file into the respective ../`arch -k`/subr.s file.
450Sstevel@tonic-gate */
460Sstevel@tonic-gate
470Sstevel@tonic-gate#include <sys/asm_linkage.h>
480Sstevel@tonic-gate#include <sys/asm_misc.h>
490Sstevel@tonic-gate#include <sys/panic.h>
500Sstevel@tonic-gate#include <sys/ontrap.h>
510Sstevel@tonic-gate#include <sys/regset.h>
520Sstevel@tonic-gate#include <sys/privregs.h>
530Sstevel@tonic-gate#include <sys/reboot.h>
540Sstevel@tonic-gate#include <sys/psw.h>
550Sstevel@tonic-gate#include <sys/x86_archext.h>
560Sstevel@tonic-gate
570Sstevel@tonic-gate#if defined(__lint)
580Sstevel@tonic-gate#include <sys/types.h>
590Sstevel@tonic-gate#include <sys/systm.h>
600Sstevel@tonic-gate#include <sys/thread.h>
610Sstevel@tonic-gate#include <sys/archsystm.h>
620Sstevel@tonic-gate#include <sys/byteorder.h>
630Sstevel@tonic-gate#include <sys/dtrace.h>
643647Sbs21162#include <sys/ftrace.h>
650Sstevel@tonic-gate#else	/* __lint */
660Sstevel@tonic-gate#include "assym.h"
670Sstevel@tonic-gate#endif	/* __lint */
680Sstevel@tonic-gate#include <sys/dditypes.h>
690Sstevel@tonic-gate
700Sstevel@tonic-gate/*
710Sstevel@tonic-gate * on_fault()
720Sstevel@tonic-gate * Catch lofault faults. Like setjmp except it returns one
730Sstevel@tonic-gate * if code following causes uncorrectable fault. Turned off
740Sstevel@tonic-gate * by calling no_fault().
750Sstevel@tonic-gate */
760Sstevel@tonic-gate
770Sstevel@tonic-gate#if defined(__lint)
780Sstevel@tonic-gate
790Sstevel@tonic-gate/* ARGSUSED */
800Sstevel@tonic-gateint
810Sstevel@tonic-gateon_fault(label_t *ljb)
820Sstevel@tonic-gate{ return (0); }
830Sstevel@tonic-gate
840Sstevel@tonic-gatevoid
850Sstevel@tonic-gateno_fault(void)
860Sstevel@tonic-gate{}
870Sstevel@tonic-gate
880Sstevel@tonic-gate#else	/* __lint */
890Sstevel@tonic-gate
900Sstevel@tonic-gate#if defined(__amd64)
910Sstevel@tonic-gate
920Sstevel@tonic-gate	ENTRY(on_fault)
930Sstevel@tonic-gate	movq	%gs:CPU_THREAD, %rsi
940Sstevel@tonic-gate	leaq	catch_fault(%rip), %rdx
950Sstevel@tonic-gate	movq	%rdi, T_ONFAULT(%rsi)		/* jumpbuf in t_onfault */
960Sstevel@tonic-gate	movq	%rdx, T_LOFAULT(%rsi)		/* catch_fault in t_lofault */
970Sstevel@tonic-gate	jmp	setjmp				/* let setjmp do the rest */
980Sstevel@tonic-gate
990Sstevel@tonic-gatecatch_fault:
1000Sstevel@tonic-gate	movq	%gs:CPU_THREAD, %rsi
1010Sstevel@tonic-gate	movq	T_ONFAULT(%rsi), %rdi		/* address of save area */
1020Sstevel@tonic-gate	xorl	%eax, %eax
1030Sstevel@tonic-gate	movq	%rax, T_ONFAULT(%rsi)		/* turn off onfault */
1040Sstevel@tonic-gate	movq	%rax, T_LOFAULT(%rsi)		/* turn off lofault */
1050Sstevel@tonic-gate	jmp	longjmp				/* let longjmp do the rest */
1060Sstevel@tonic-gate	SET_SIZE(on_fault)
1070Sstevel@tonic-gate
1080Sstevel@tonic-gate	ENTRY(no_fault)
1090Sstevel@tonic-gate	movq	%gs:CPU_THREAD, %rsi
1100Sstevel@tonic-gate	xorl	%eax, %eax
1110Sstevel@tonic-gate	movq	%rax, T_ONFAULT(%rsi)		/* turn off onfault */
1120Sstevel@tonic-gate	movq	%rax, T_LOFAULT(%rsi)		/* turn off lofault */
1130Sstevel@tonic-gate	ret
1140Sstevel@tonic-gate	SET_SIZE(no_fault)
1150Sstevel@tonic-gate
1160Sstevel@tonic-gate#elif defined(__i386)
1177421SDaniel.Anderson@Sun.COM
1180Sstevel@tonic-gate	ENTRY(on_fault)
1190Sstevel@tonic-gate	movl	%gs:CPU_THREAD, %edx
1200Sstevel@tonic-gate	movl	4(%esp), %eax			/* jumpbuf address */
1210Sstevel@tonic-gate	leal	catch_fault, %ecx
1220Sstevel@tonic-gate	movl	%eax, T_ONFAULT(%edx)		/* jumpbuf in t_onfault */
1230Sstevel@tonic-gate	movl	%ecx, T_LOFAULT(%edx)		/* catch_fault in t_lofault */
1240Sstevel@tonic-gate	jmp	setjmp				/* let setjmp do the rest */
1250Sstevel@tonic-gate
1260Sstevel@tonic-gatecatch_fault:
1270Sstevel@tonic-gate	movl	%gs:CPU_THREAD, %edx
1280Sstevel@tonic-gate	xorl	%eax, %eax
1290Sstevel@tonic-gate	movl	T_ONFAULT(%edx), %ecx		/* address of save area */
1300Sstevel@tonic-gate	movl	%eax, T_ONFAULT(%edx)		/* turn off onfault */
1310Sstevel@tonic-gate	movl	%eax, T_LOFAULT(%edx)		/* turn off lofault */
1320Sstevel@tonic-gate	pushl	%ecx
1330Sstevel@tonic-gate	call	longjmp				/* let longjmp do the rest */
1340Sstevel@tonic-gate	SET_SIZE(on_fault)
1350Sstevel@tonic-gate
1360Sstevel@tonic-gate	ENTRY(no_fault)
1370Sstevel@tonic-gate	movl	%gs:CPU_THREAD, %edx
1380Sstevel@tonic-gate	xorl	%eax, %eax
1390Sstevel@tonic-gate	movl	%eax, T_ONFAULT(%edx)		/* turn off onfault */
1400Sstevel@tonic-gate	movl	%eax, T_LOFAULT(%edx)		/* turn off lofault */
1410Sstevel@tonic-gate	ret
1420Sstevel@tonic-gate	SET_SIZE(no_fault)
1430Sstevel@tonic-gate
1440Sstevel@tonic-gate#endif	/* __i386 */
1450Sstevel@tonic-gate#endif	/* __lint */
1460Sstevel@tonic-gate
1470Sstevel@tonic-gate/*
1480Sstevel@tonic-gate * Default trampoline code for on_trap() (see <sys/ontrap.h>).  We just
1490Sstevel@tonic-gate * do a longjmp(&curthread->t_ontrap->ot_jmpbuf) if this is ever called.
1500Sstevel@tonic-gate */
1510Sstevel@tonic-gate
1520Sstevel@tonic-gate#if defined(lint)
1530Sstevel@tonic-gate
1540Sstevel@tonic-gatevoid
1550Sstevel@tonic-gateon_trap_trampoline(void)
1560Sstevel@tonic-gate{}
1570Sstevel@tonic-gate
1580Sstevel@tonic-gate#else	/* __lint */
1590Sstevel@tonic-gate
1600Sstevel@tonic-gate#if defined(__amd64)
1610Sstevel@tonic-gate
1620Sstevel@tonic-gate	ENTRY(on_trap_trampoline)
1630Sstevel@tonic-gate	movq	%gs:CPU_THREAD, %rsi
1640Sstevel@tonic-gate	movq	T_ONTRAP(%rsi), %rdi
1650Sstevel@tonic-gate	addq	$OT_JMPBUF, %rdi
1660Sstevel@tonic-gate	jmp	longjmp
1670Sstevel@tonic-gate	SET_SIZE(on_trap_trampoline)
1680Sstevel@tonic-gate
1690Sstevel@tonic-gate#elif defined(__i386)
1700Sstevel@tonic-gate
1710Sstevel@tonic-gate	ENTRY(on_trap_trampoline)
1720Sstevel@tonic-gate	movl	%gs:CPU_THREAD, %eax
1730Sstevel@tonic-gate	movl	T_ONTRAP(%eax), %eax
1740Sstevel@tonic-gate	addl	$OT_JMPBUF, %eax
1750Sstevel@tonic-gate	pushl	%eax
1760Sstevel@tonic-gate	call	longjmp
1770Sstevel@tonic-gate	SET_SIZE(on_trap_trampoline)
1780Sstevel@tonic-gate
1790Sstevel@tonic-gate#endif	/* __i386 */
1800Sstevel@tonic-gate#endif	/* __lint */
1810Sstevel@tonic-gate
1820Sstevel@tonic-gate/*
1830Sstevel@tonic-gate * Push a new element on to the t_ontrap stack.  Refer to <sys/ontrap.h> for
1840Sstevel@tonic-gate * more information about the on_trap() mechanism.  If the on_trap_data is the
1850Sstevel@tonic-gate * same as the topmost stack element, we just modify that element.
1860Sstevel@tonic-gate */
1870Sstevel@tonic-gate#if defined(lint)
1880Sstevel@tonic-gate
1890Sstevel@tonic-gate/*ARGSUSED*/
1900Sstevel@tonic-gateint
1910Sstevel@tonic-gateon_trap(on_trap_data_t *otp, uint_t prot)
1920Sstevel@tonic-gate{ return (0); }
1930Sstevel@tonic-gate
1940Sstevel@tonic-gate#else	/* __lint */
1950Sstevel@tonic-gate
1960Sstevel@tonic-gate#if defined(__amd64)
1970Sstevel@tonic-gate
1980Sstevel@tonic-gate	ENTRY(on_trap)
1990Sstevel@tonic-gate	movw	%si, OT_PROT(%rdi)		/* ot_prot = prot */
2000Sstevel@tonic-gate	movw	$0, OT_TRAP(%rdi)		/* ot_trap = 0 */
2010Sstevel@tonic-gate	leaq	on_trap_trampoline(%rip), %rdx	/* rdx = &on_trap_trampoline */
2020Sstevel@tonic-gate	movq	%rdx, OT_TRAMPOLINE(%rdi)	/* ot_trampoline = rdx */
2030Sstevel@tonic-gate	xorl	%ecx, %ecx
2040Sstevel@tonic-gate	movq	%rcx, OT_HANDLE(%rdi)		/* ot_handle = NULL */
2050Sstevel@tonic-gate	movq	%rcx, OT_PAD1(%rdi)		/* ot_pad1 = NULL */
2060Sstevel@tonic-gate	movq	%gs:CPU_THREAD, %rdx		/* rdx = curthread */
2070Sstevel@tonic-gate	movq	T_ONTRAP(%rdx), %rcx		/* rcx = curthread->t_ontrap */
2080Sstevel@tonic-gate	cmpq	%rdi, %rcx			/* if (otp == %rcx)	*/
2090Sstevel@tonic-gate	je	0f				/*	don't modify t_ontrap */
2100Sstevel@tonic-gate
2110Sstevel@tonic-gate	movq	%rcx, OT_PREV(%rdi)		/* ot_prev = t_ontrap */
2120Sstevel@tonic-gate	movq	%rdi, T_ONTRAP(%rdx)		/* curthread->t_ontrap = otp */
2130Sstevel@tonic-gate
2140Sstevel@tonic-gate0:	addq	$OT_JMPBUF, %rdi		/* &ot_jmpbuf */
2150Sstevel@tonic-gate	jmp	setjmp
2160Sstevel@tonic-gate	SET_SIZE(on_trap)
2170Sstevel@tonic-gate
2180Sstevel@tonic-gate#elif defined(__i386)
2190Sstevel@tonic-gate
2200Sstevel@tonic-gate	ENTRY(on_trap)
2210Sstevel@tonic-gate	movl	4(%esp), %eax			/* %eax = otp */
2220Sstevel@tonic-gate	movl	8(%esp), %edx			/* %edx = prot */
2230Sstevel@tonic-gate
2240Sstevel@tonic-gate	movw	%dx, OT_PROT(%eax)		/* ot_prot = prot */
2250Sstevel@tonic-gate	movw	$0, OT_TRAP(%eax)		/* ot_trap = 0 */
2260Sstevel@tonic-gate	leal	on_trap_trampoline, %edx	/* %edx = &on_trap_trampoline */
2270Sstevel@tonic-gate	movl	%edx, OT_TRAMPOLINE(%eax)	/* ot_trampoline = %edx */
2280Sstevel@tonic-gate	movl	$0, OT_HANDLE(%eax)		/* ot_handle = NULL */
2290Sstevel@tonic-gate	movl	$0, OT_PAD1(%eax)		/* ot_pad1 = NULL */
2300Sstevel@tonic-gate	movl	%gs:CPU_THREAD, %edx		/* %edx = curthread */
2310Sstevel@tonic-gate	movl	T_ONTRAP(%edx), %ecx		/* %ecx = curthread->t_ontrap */
2320Sstevel@tonic-gate	cmpl	%eax, %ecx			/* if (otp == %ecx) */
2330Sstevel@tonic-gate	je	0f				/*    don't modify t_ontrap */
2340Sstevel@tonic-gate
2350Sstevel@tonic-gate	movl	%ecx, OT_PREV(%eax)		/* ot_prev = t_ontrap */
2360Sstevel@tonic-gate	movl	%eax, T_ONTRAP(%edx)		/* curthread->t_ontrap = otp */
2370Sstevel@tonic-gate
2380Sstevel@tonic-gate0:	addl	$OT_JMPBUF, %eax		/* %eax = &ot_jmpbuf */
2390Sstevel@tonic-gate	movl	%eax, 4(%esp)			/* put %eax back on the stack */
2400Sstevel@tonic-gate	jmp	setjmp				/* let setjmp do the rest */
2410Sstevel@tonic-gate	SET_SIZE(on_trap)
2420Sstevel@tonic-gate
2430Sstevel@tonic-gate#endif	/* __i386 */
2440Sstevel@tonic-gate#endif	/* __lint */
2450Sstevel@tonic-gate
2460Sstevel@tonic-gate/*
2470Sstevel@tonic-gate * Setjmp and longjmp implement non-local gotos using state vectors
2480Sstevel@tonic-gate * type label_t.
2490Sstevel@tonic-gate */
2500Sstevel@tonic-gate
2510Sstevel@tonic-gate#if defined(__lint)
2520Sstevel@tonic-gate
2530Sstevel@tonic-gate/* ARGSUSED */
2540Sstevel@tonic-gateint
2550Sstevel@tonic-gatesetjmp(label_t *lp)
2560Sstevel@tonic-gate{ return (0); }
2570Sstevel@tonic-gate
2580Sstevel@tonic-gate/* ARGSUSED */
2590Sstevel@tonic-gatevoid
2600Sstevel@tonic-gatelongjmp(label_t *lp)
2610Sstevel@tonic-gate{}
2620Sstevel@tonic-gate
2630Sstevel@tonic-gate#else	/* __lint */
2640Sstevel@tonic-gate
2650Sstevel@tonic-gate#if LABEL_PC != 0
2660Sstevel@tonic-gate#error LABEL_PC MUST be defined as 0 for setjmp/longjmp to work as coded
2670Sstevel@tonic-gate#endif	/* LABEL_PC != 0 */
2680Sstevel@tonic-gate
2690Sstevel@tonic-gate#if defined(__amd64)
2700Sstevel@tonic-gate
2710Sstevel@tonic-gate	ENTRY(setjmp)
2720Sstevel@tonic-gate	movq	%rsp, LABEL_SP(%rdi)
2730Sstevel@tonic-gate	movq	%rbp, LABEL_RBP(%rdi)
2740Sstevel@tonic-gate	movq	%rbx, LABEL_RBX(%rdi)
2750Sstevel@tonic-gate	movq	%r12, LABEL_R12(%rdi)
2760Sstevel@tonic-gate	movq	%r13, LABEL_R13(%rdi)
2770Sstevel@tonic-gate	movq	%r14, LABEL_R14(%rdi)
2780Sstevel@tonic-gate	movq	%r15, LABEL_R15(%rdi)
2790Sstevel@tonic-gate	movq	(%rsp), %rdx		/* return address */
2800Sstevel@tonic-gate	movq	%rdx, (%rdi)		/* LABEL_PC is 0 */
2810Sstevel@tonic-gate	xorl	%eax, %eax		/* return 0 */
2820Sstevel@tonic-gate	ret
2830Sstevel@tonic-gate	SET_SIZE(setjmp)
2840Sstevel@tonic-gate
2850Sstevel@tonic-gate	ENTRY(longjmp)
2860Sstevel@tonic-gate	movq	LABEL_SP(%rdi), %rsp
2870Sstevel@tonic-gate	movq	LABEL_RBP(%rdi), %rbp
2880Sstevel@tonic-gate	movq	LABEL_RBX(%rdi), %rbx
2890Sstevel@tonic-gate	movq	LABEL_R12(%rdi), %r12
2900Sstevel@tonic-gate	movq	LABEL_R13(%rdi), %r13
2910Sstevel@tonic-gate	movq	LABEL_R14(%rdi), %r14
2920Sstevel@tonic-gate	movq	LABEL_R15(%rdi), %r15
2930Sstevel@tonic-gate	movq	(%rdi), %rdx		/* return address; LABEL_PC is 0 */
2940Sstevel@tonic-gate	movq	%rdx, (%rsp)
2950Sstevel@tonic-gate	xorl	%eax, %eax
2960Sstevel@tonic-gate	incl	%eax			/* return 1 */
2970Sstevel@tonic-gate	ret
2980Sstevel@tonic-gate	SET_SIZE(longjmp)
2990Sstevel@tonic-gate
3000Sstevel@tonic-gate#elif defined(__i386)
3010Sstevel@tonic-gate
3020Sstevel@tonic-gate	ENTRY(setjmp)
3030Sstevel@tonic-gate	movl	4(%esp), %edx		/* address of save area */
3040Sstevel@tonic-gate	movl	%ebp, LABEL_EBP(%edx)
3050Sstevel@tonic-gate	movl	%ebx, LABEL_EBX(%edx)
3060Sstevel@tonic-gate	movl	%esi, LABEL_ESI(%edx)
3070Sstevel@tonic-gate	movl	%edi, LABEL_EDI(%edx)
3080Sstevel@tonic-gate	movl	%esp, 4(%edx)
3090Sstevel@tonic-gate	movl	(%esp), %ecx		/* %eip (return address) */
3100Sstevel@tonic-gate	movl	%ecx, (%edx)		/* LABEL_PC is 0 */
3110Sstevel@tonic-gate	subl	%eax, %eax		/* return 0 */
3120Sstevel@tonic-gate	ret
3130Sstevel@tonic-gate	SET_SIZE(setjmp)
3140Sstevel@tonic-gate
3150Sstevel@tonic-gate	ENTRY(longjmp)
3160Sstevel@tonic-gate	movl	4(%esp), %edx		/* address of save area */
3170Sstevel@tonic-gate	movl	LABEL_EBP(%edx), %ebp
3180Sstevel@tonic-gate	movl	LABEL_EBX(%edx), %ebx
3190Sstevel@tonic-gate	movl	LABEL_ESI(%edx), %esi
3200Sstevel@tonic-gate	movl	LABEL_EDI(%edx), %edi
3210Sstevel@tonic-gate	movl	4(%edx), %esp
3220Sstevel@tonic-gate	movl	(%edx), %ecx		/* %eip (return addr); LABEL_PC is 0 */
3230Sstevel@tonic-gate	movl	$1, %eax
3240Sstevel@tonic-gate	addl	$4, %esp		/* pop ret adr */
3250Sstevel@tonic-gate	jmp	*%ecx			/* indirect */
3260Sstevel@tonic-gate	SET_SIZE(longjmp)
3270Sstevel@tonic-gate
3280Sstevel@tonic-gate#endif	/* __i386 */
3290Sstevel@tonic-gate#endif	/* __lint */
3300Sstevel@tonic-gate
3310Sstevel@tonic-gate/*
3320Sstevel@tonic-gate * if a() calls b() calls caller(),
3330Sstevel@tonic-gate * caller() returns return address in a().
3340Sstevel@tonic-gate * (Note: We assume a() and b() are C routines which do the normal entry/exit
3350Sstevel@tonic-gate *  sequence.)
3360Sstevel@tonic-gate */
3370Sstevel@tonic-gate
3380Sstevel@tonic-gate#if defined(__lint)
3390Sstevel@tonic-gate
3400Sstevel@tonic-gatecaddr_t
3410Sstevel@tonic-gatecaller(void)
3420Sstevel@tonic-gate{ return (0); }
3430Sstevel@tonic-gate
3440Sstevel@tonic-gate#else	/* __lint */
3450Sstevel@tonic-gate
3460Sstevel@tonic-gate#if defined(__amd64)
3470Sstevel@tonic-gate
3480Sstevel@tonic-gate	ENTRY(caller)
3490Sstevel@tonic-gate	movq	8(%rbp), %rax		/* b()'s return pc, in a() */
3500Sstevel@tonic-gate	ret
3510Sstevel@tonic-gate	SET_SIZE(caller)
3520Sstevel@tonic-gate
3530Sstevel@tonic-gate#elif defined(__i386)
3540Sstevel@tonic-gate
3550Sstevel@tonic-gate	ENTRY(caller)
3560Sstevel@tonic-gate	movl	4(%ebp), %eax		/* b()'s return pc, in a() */
3570Sstevel@tonic-gate	ret
3580Sstevel@tonic-gate	SET_SIZE(caller)
3590Sstevel@tonic-gate
3600Sstevel@tonic-gate#endif	/* __i386 */
3610Sstevel@tonic-gate#endif	/* __lint */
3620Sstevel@tonic-gate
3630Sstevel@tonic-gate/*
3640Sstevel@tonic-gate * if a() calls callee(), callee() returns the
3650Sstevel@tonic-gate * return address in a();
3660Sstevel@tonic-gate */
3670Sstevel@tonic-gate
3680Sstevel@tonic-gate#if defined(__lint)
3690Sstevel@tonic-gate
3700Sstevel@tonic-gatecaddr_t
3710Sstevel@tonic-gatecallee(void)
3720Sstevel@tonic-gate{ return (0); }
3730Sstevel@tonic-gate
3740Sstevel@tonic-gate#else	/* __lint */
3750Sstevel@tonic-gate
3760Sstevel@tonic-gate#if defined(__amd64)
3770Sstevel@tonic-gate
3780Sstevel@tonic-gate	ENTRY(callee)
3790Sstevel@tonic-gate	movq	(%rsp), %rax		/* callee()'s return pc, in a() */
3800Sstevel@tonic-gate	ret
3810Sstevel@tonic-gate	SET_SIZE(callee)
3820Sstevel@tonic-gate
3830Sstevel@tonic-gate#elif defined(__i386)
3840Sstevel@tonic-gate
3850Sstevel@tonic-gate	ENTRY(callee)
3860Sstevel@tonic-gate	movl	(%esp), %eax		/* callee()'s return pc, in a() */
3870Sstevel@tonic-gate	ret
3880Sstevel@tonic-gate	SET_SIZE(callee)
3890Sstevel@tonic-gate
3900Sstevel@tonic-gate#endif	/* __i386 */
3910Sstevel@tonic-gate#endif	/* __lint */
3920Sstevel@tonic-gate
3930Sstevel@tonic-gate/*
3940Sstevel@tonic-gate * return the current frame pointer
3950Sstevel@tonic-gate */
3960Sstevel@tonic-gate
3970Sstevel@tonic-gate#if defined(__lint)
3980Sstevel@tonic-gate
3990Sstevel@tonic-gategreg_t
4000Sstevel@tonic-gategetfp(void)
4010Sstevel@tonic-gate{ return (0); }
4020Sstevel@tonic-gate
4030Sstevel@tonic-gate#else	/* __lint */
4040Sstevel@tonic-gate
4050Sstevel@tonic-gate#if defined(__amd64)
4060Sstevel@tonic-gate
4070Sstevel@tonic-gate	ENTRY(getfp)
4080Sstevel@tonic-gate	movq	%rbp, %rax
4090Sstevel@tonic-gate	ret
4100Sstevel@tonic-gate	SET_SIZE(getfp)
4110Sstevel@tonic-gate
4120Sstevel@tonic-gate#elif defined(__i386)
4130Sstevel@tonic-gate
4140Sstevel@tonic-gate	ENTRY(getfp)
4150Sstevel@tonic-gate	movl	%ebp, %eax
4160Sstevel@tonic-gate	ret
4170Sstevel@tonic-gate	SET_SIZE(getfp)
4180Sstevel@tonic-gate
4190Sstevel@tonic-gate#endif	/* __i386 */
4200Sstevel@tonic-gate#endif	/* __lint */
4210Sstevel@tonic-gate
4220Sstevel@tonic-gate/*
4230Sstevel@tonic-gate * Invalidate a single page table entry in the TLB
4240Sstevel@tonic-gate */
4250Sstevel@tonic-gate
4260Sstevel@tonic-gate#if defined(__lint)
4270Sstevel@tonic-gate
4280Sstevel@tonic-gate/* ARGSUSED */
4290Sstevel@tonic-gatevoid
4300Sstevel@tonic-gatemmu_tlbflush_entry(caddr_t m)
4310Sstevel@tonic-gate{}
4320Sstevel@tonic-gate
4330Sstevel@tonic-gate#else	/* __lint */
4340Sstevel@tonic-gate
4350Sstevel@tonic-gate#if defined(__amd64)
4360Sstevel@tonic-gate
4370Sstevel@tonic-gate	ENTRY(mmu_tlbflush_entry)
4380Sstevel@tonic-gate	invlpg	(%rdi)
4390Sstevel@tonic-gate	ret
4400Sstevel@tonic-gate	SET_SIZE(mmu_tlbflush_entry)
4410Sstevel@tonic-gate
4420Sstevel@tonic-gate#elif defined(__i386)
4430Sstevel@tonic-gate
4440Sstevel@tonic-gate	ENTRY(mmu_tlbflush_entry)
4450Sstevel@tonic-gate	movl	4(%esp), %eax
4460Sstevel@tonic-gate	invlpg	(%eax)
4470Sstevel@tonic-gate	ret
4480Sstevel@tonic-gate	SET_SIZE(mmu_tlbflush_entry)
4490Sstevel@tonic-gate
4500Sstevel@tonic-gate#endif	/* __i386 */
4510Sstevel@tonic-gate#endif	/* __lint */
4520Sstevel@tonic-gate
4530Sstevel@tonic-gate
4540Sstevel@tonic-gate/*
4550Sstevel@tonic-gate * Get/Set the value of various control registers
4560Sstevel@tonic-gate */
4570Sstevel@tonic-gate
4580Sstevel@tonic-gate#if defined(__lint)
4590Sstevel@tonic-gate
4600Sstevel@tonic-gateulong_t
4610Sstevel@tonic-gategetcr0(void)
4620Sstevel@tonic-gate{ return (0); }
4630Sstevel@tonic-gate
4640Sstevel@tonic-gate/* ARGSUSED */
4650Sstevel@tonic-gatevoid
4660Sstevel@tonic-gatesetcr0(ulong_t value)
4670Sstevel@tonic-gate{}
4680Sstevel@tonic-gate
4690Sstevel@tonic-gateulong_t
4700Sstevel@tonic-gategetcr2(void)
4710Sstevel@tonic-gate{ return (0); }
4720Sstevel@tonic-gate
4730Sstevel@tonic-gateulong_t
4740Sstevel@tonic-gategetcr3(void)
4750Sstevel@tonic-gate{ return (0); }
4760Sstevel@tonic-gate
4775084Sjohnlev#if !defined(__xpv)
4780Sstevel@tonic-gate/* ARGSUSED */
4790Sstevel@tonic-gatevoid
4800Sstevel@tonic-gatesetcr3(ulong_t val)
4810Sstevel@tonic-gate{}
4820Sstevel@tonic-gate
4830Sstevel@tonic-gatevoid
4840Sstevel@tonic-gatereload_cr3(void)
4850Sstevel@tonic-gate{}
4865084Sjohnlev#endif
4870Sstevel@tonic-gate
4880Sstevel@tonic-gateulong_t
4890Sstevel@tonic-gategetcr4(void)
4900Sstevel@tonic-gate{ return (0); }
4910Sstevel@tonic-gate
4920Sstevel@tonic-gate/* ARGSUSED */
4930Sstevel@tonic-gatevoid
4940Sstevel@tonic-gatesetcr4(ulong_t val)
4950Sstevel@tonic-gate{}
4960Sstevel@tonic-gate
4970Sstevel@tonic-gate#if defined(__amd64)
4980Sstevel@tonic-gate
4990Sstevel@tonic-gateulong_t
5000Sstevel@tonic-gategetcr8(void)
5010Sstevel@tonic-gate{ return (0); }
5020Sstevel@tonic-gate
5030Sstevel@tonic-gate/* ARGSUSED */
5040Sstevel@tonic-gatevoid
5050Sstevel@tonic-gatesetcr8(ulong_t val)
5060Sstevel@tonic-gate{}
5070Sstevel@tonic-gate
5080Sstevel@tonic-gate#endif	/* __amd64 */
5090Sstevel@tonic-gate
5100Sstevel@tonic-gate#else	/* __lint */
5110Sstevel@tonic-gate
5120Sstevel@tonic-gate#if defined(__amd64)
5130Sstevel@tonic-gate
5140Sstevel@tonic-gate	ENTRY(getcr0)
5150Sstevel@tonic-gate	movq	%cr0, %rax
5160Sstevel@tonic-gate	ret
5170Sstevel@tonic-gate	SET_SIZE(getcr0)
5180Sstevel@tonic-gate
5190Sstevel@tonic-gate	ENTRY(setcr0)
5200Sstevel@tonic-gate	movq	%rdi, %cr0
5210Sstevel@tonic-gate	ret
5220Sstevel@tonic-gate	SET_SIZE(setcr0)
5230Sstevel@tonic-gate
5243446Smrj        ENTRY(getcr2)
5255084Sjohnlev#if defined(__xpv)
5265084Sjohnlev	movq	%gs:CPU_VCPU_INFO, %rax
5275084Sjohnlev	movq	VCPU_INFO_ARCH_CR2(%rax), %rax
5285084Sjohnlev#else
5293446Smrj        movq    %cr2, %rax
5305084Sjohnlev#endif
5313446Smrj        ret
5320Sstevel@tonic-gate	SET_SIZE(getcr2)
5330Sstevel@tonic-gate
5340Sstevel@tonic-gate	ENTRY(getcr3)
5353446Smrj	movq    %cr3, %rax
5360Sstevel@tonic-gate	ret
5370Sstevel@tonic-gate	SET_SIZE(getcr3)
5380Sstevel@tonic-gate
5395084Sjohnlev#if !defined(__xpv)
5405084Sjohnlev
5413446Smrj        ENTRY(setcr3)
5423446Smrj        movq    %rdi, %cr3
5433446Smrj        ret
5440Sstevel@tonic-gate	SET_SIZE(setcr3)
5450Sstevel@tonic-gate
5460Sstevel@tonic-gate	ENTRY(reload_cr3)
5470Sstevel@tonic-gate	movq	%cr3, %rdi
5480Sstevel@tonic-gate	movq	%rdi, %cr3
5490Sstevel@tonic-gate	ret
5500Sstevel@tonic-gate	SET_SIZE(reload_cr3)
5510Sstevel@tonic-gate
5525084Sjohnlev#endif	/* __xpv */
5535084Sjohnlev
5540Sstevel@tonic-gate	ENTRY(getcr4)
5550Sstevel@tonic-gate	movq	%cr4, %rax
5560Sstevel@tonic-gate	ret
5570Sstevel@tonic-gate	SET_SIZE(getcr4)
5580Sstevel@tonic-gate
5590Sstevel@tonic-gate	ENTRY(setcr4)
5600Sstevel@tonic-gate	movq	%rdi, %cr4
5610Sstevel@tonic-gate	ret
5620Sstevel@tonic-gate	SET_SIZE(setcr4)
5630Sstevel@tonic-gate
5640Sstevel@tonic-gate	ENTRY(getcr8)
5650Sstevel@tonic-gate	movq	%cr8, %rax
5660Sstevel@tonic-gate	ret
5670Sstevel@tonic-gate	SET_SIZE(getcr8)
5680Sstevel@tonic-gate
5690Sstevel@tonic-gate	ENTRY(setcr8)
5700Sstevel@tonic-gate	movq	%rdi, %cr8
5710Sstevel@tonic-gate	ret
5720Sstevel@tonic-gate	SET_SIZE(setcr8)
5730Sstevel@tonic-gate
5740Sstevel@tonic-gate#elif defined(__i386)
5750Sstevel@tonic-gate
5760Sstevel@tonic-gate        ENTRY(getcr0)
5770Sstevel@tonic-gate        movl    %cr0, %eax
5780Sstevel@tonic-gate        ret
5790Sstevel@tonic-gate	SET_SIZE(getcr0)
5800Sstevel@tonic-gate
5810Sstevel@tonic-gate        ENTRY(setcr0)
5820Sstevel@tonic-gate        movl    4(%esp), %eax
5830Sstevel@tonic-gate        movl    %eax, %cr0
5840Sstevel@tonic-gate        ret
5850Sstevel@tonic-gate	SET_SIZE(setcr0)
5860Sstevel@tonic-gate
58710080SJoe.Bonasera@sun.com	/*
58810080SJoe.Bonasera@sun.com	 * "lock mov %cr0" is used on processors which indicate it is
58910080SJoe.Bonasera@sun.com	 * supported via CPUID. Normally the 32 bit TPR is accessed via
59010080SJoe.Bonasera@sun.com	 * the local APIC.
59110080SJoe.Bonasera@sun.com	 */
59210080SJoe.Bonasera@sun.com	ENTRY(getcr8)
59310080SJoe.Bonasera@sun.com	lock
59410080SJoe.Bonasera@sun.com	movl	%cr0, %eax
59510080SJoe.Bonasera@sun.com	ret
59610080SJoe.Bonasera@sun.com	SET_SIZE(getcr8)
59710080SJoe.Bonasera@sun.com
59810080SJoe.Bonasera@sun.com	ENTRY(setcr8)
59910080SJoe.Bonasera@sun.com        movl    4(%esp), %eax
60010080SJoe.Bonasera@sun.com	lock
60110080SJoe.Bonasera@sun.com        movl    %eax, %cr0
60210080SJoe.Bonasera@sun.com	ret
60310080SJoe.Bonasera@sun.com	SET_SIZE(setcr8)
60410080SJoe.Bonasera@sun.com
6050Sstevel@tonic-gate        ENTRY(getcr2)
6065084Sjohnlev#if defined(__xpv)
6075084Sjohnlev	movl	%gs:CPU_VCPU_INFO, %eax
6085084Sjohnlev	movl	VCPU_INFO_ARCH_CR2(%eax), %eax
6095084Sjohnlev#else
6100Sstevel@tonic-gate        movl    %cr2, %eax
6115084Sjohnlev#endif
6120Sstevel@tonic-gate        ret
6130Sstevel@tonic-gate	SET_SIZE(getcr2)
6140Sstevel@tonic-gate
6150Sstevel@tonic-gate	ENTRY(getcr3)
6160Sstevel@tonic-gate	movl    %cr3, %eax
6170Sstevel@tonic-gate	ret
6180Sstevel@tonic-gate	SET_SIZE(getcr3)
6190Sstevel@tonic-gate
6205084Sjohnlev#if !defined(__xpv)
6215084Sjohnlev
6220Sstevel@tonic-gate        ENTRY(setcr3)
6230Sstevel@tonic-gate        movl    4(%esp), %eax
6240Sstevel@tonic-gate        movl    %eax, %cr3
6250Sstevel@tonic-gate        ret
6260Sstevel@tonic-gate	SET_SIZE(setcr3)
6270Sstevel@tonic-gate
6280Sstevel@tonic-gate	ENTRY(reload_cr3)
6290Sstevel@tonic-gate	movl    %cr3, %eax
6300Sstevel@tonic-gate	movl    %eax, %cr3
6310Sstevel@tonic-gate	ret
6320Sstevel@tonic-gate	SET_SIZE(reload_cr3)
6330Sstevel@tonic-gate
6345084Sjohnlev#endif	/* __xpv */
6355084Sjohnlev
6360Sstevel@tonic-gate	ENTRY(getcr4)
6370Sstevel@tonic-gate	movl    %cr4, %eax
6380Sstevel@tonic-gate	ret
6390Sstevel@tonic-gate	SET_SIZE(getcr4)
6400Sstevel@tonic-gate
6410Sstevel@tonic-gate        ENTRY(setcr4)
6420Sstevel@tonic-gate        movl    4(%esp), %eax
6430Sstevel@tonic-gate        movl    %eax, %cr4
6440Sstevel@tonic-gate        ret
6450Sstevel@tonic-gate	SET_SIZE(setcr4)
6460Sstevel@tonic-gate
6470Sstevel@tonic-gate#endif	/* __i386 */
6480Sstevel@tonic-gate#endif	/* __lint */
6490Sstevel@tonic-gate
6500Sstevel@tonic-gate#if defined(__lint)
6510Sstevel@tonic-gate
6520Sstevel@tonic-gate/*ARGSUSED*/
6530Sstevel@tonic-gateuint32_t
6541228Sandrei__cpuid_insn(struct cpuid_regs *regs)
6550Sstevel@tonic-gate{ return (0); }
6560Sstevel@tonic-gate
6570Sstevel@tonic-gate#else	/* __lint */
6580Sstevel@tonic-gate
6590Sstevel@tonic-gate#if defined(__amd64)
6600Sstevel@tonic-gate
6610Sstevel@tonic-gate	ENTRY(__cpuid_insn)
6621228Sandrei	movq	%rbx, %r8
6631228Sandrei	movq	%rcx, %r9
6641228Sandrei	movq	%rdx, %r11
6651228Sandrei	movl	(%rdi), %eax		/* %eax = regs->cp_eax */
6661228Sandrei	movl	0x4(%rdi), %ebx		/* %ebx = regs->cp_ebx */
6671228Sandrei	movl	0x8(%rdi), %ecx		/* %ecx = regs->cp_ecx */
6681228Sandrei	movl	0xc(%rdi), %edx		/* %edx = regs->cp_edx */
6690Sstevel@tonic-gate	cpuid
6701228Sandrei	movl	%eax, (%rdi)		/* regs->cp_eax = %eax */
6711228Sandrei	movl	%ebx, 0x4(%rdi)		/* regs->cp_ebx = %ebx */
6721228Sandrei	movl	%ecx, 0x8(%rdi)		/* regs->cp_ecx = %ecx */
6731228Sandrei	movl	%edx, 0xc(%rdi)		/* regs->cp_edx = %edx */
6741228Sandrei	movq	%r8, %rbx
6751228Sandrei	movq	%r9, %rcx
6761228Sandrei	movq	%r11, %rdx
6770Sstevel@tonic-gate	ret
6780Sstevel@tonic-gate	SET_SIZE(__cpuid_insn)
6790Sstevel@tonic-gate
6800Sstevel@tonic-gate#elif defined(__i386)
6810Sstevel@tonic-gate
6820Sstevel@tonic-gate        ENTRY(__cpuid_insn)
6830Sstevel@tonic-gate	pushl	%ebp
6841228Sandrei	movl	0x8(%esp), %ebp		/* %ebp = regs */
6850Sstevel@tonic-gate	pushl	%ebx
6861228Sandrei	pushl	%ecx
6871228Sandrei	pushl	%edx
6881228Sandrei	movl	(%ebp), %eax		/* %eax = regs->cp_eax */
6891228Sandrei	movl	0x4(%ebp), %ebx		/* %ebx = regs->cp_ebx */
6901228Sandrei	movl	0x8(%ebp), %ecx		/* %ecx = regs->cp_ecx */
6911228Sandrei	movl	0xc(%ebp), %edx		/* %edx = regs->cp_edx */
6920Sstevel@tonic-gate	cpuid
6931228Sandrei	movl	%eax, (%ebp)		/* regs->cp_eax = %eax */
6941228Sandrei	movl	%ebx, 0x4(%ebp)		/* regs->cp_ebx = %ebx */
6951228Sandrei	movl	%ecx, 0x8(%ebp)		/* regs->cp_ecx = %ecx */
6961228Sandrei	movl	%edx, 0xc(%ebp)		/* regs->cp_edx = %edx */
6971228Sandrei	popl	%edx
6981228Sandrei	popl	%ecx
6990Sstevel@tonic-gate	popl	%ebx
7000Sstevel@tonic-gate	popl	%ebp
7010Sstevel@tonic-gate	ret
7020Sstevel@tonic-gate	SET_SIZE(__cpuid_insn)
7030Sstevel@tonic-gate
7040Sstevel@tonic-gate#endif	/* __i386 */
7050Sstevel@tonic-gate#endif	/* __lint */
7060Sstevel@tonic-gate
7074481Sbholler#if defined(__lint)
7084481Sbholler
7094481Sbholler/*ARGSUSED*/
7104481Sbhollervoid
7114481Sbholleri86_monitor(volatile uint32_t *addr, uint32_t extensions, uint32_t hints)
7129489SJoe.Bonasera@sun.com{}
7134481Sbholler
7144481Sbholler#else   /* __lint */
7154481Sbholler
7164481Sbholler#if defined(__amd64)
7174481Sbholler
7184481Sbholler	ENTRY_NP(i86_monitor)
7194481Sbholler	pushq	%rbp
7204481Sbholler	movq	%rsp, %rbp
7214481Sbholler	movq	%rdi, %rax		/* addr */
7224481Sbholler	movq	%rsi, %rcx		/* extensions */
7234481Sbholler	/* rdx contains input arg3: hints */
7247716SBill.Holler@Sun.COM	clflush	(%rax)
7254481Sbholler	.byte	0x0f, 0x01, 0xc8	/* monitor */
7264481Sbholler	leave
7274481Sbholler	ret
7284481Sbholler	SET_SIZE(i86_monitor)
7294481Sbholler
7304481Sbholler#elif defined(__i386)
7314481Sbholler
7324481SbhollerENTRY_NP(i86_monitor)
7334481Sbholler	pushl	%ebp
7344481Sbholler	movl	%esp, %ebp
7354501Sbholler	movl	0x8(%ebp),%eax		/* addr */
7364501Sbholler	movl	0xc(%ebp),%ecx		/* extensions */
7374501Sbholler	movl	0x10(%ebp),%edx		/* hints */
7387716SBill.Holler@Sun.COM	clflush	(%eax)
7394481Sbholler	.byte	0x0f, 0x01, 0xc8	/* monitor */
7404481Sbholler	leave
7414481Sbholler	ret
7424481Sbholler	SET_SIZE(i86_monitor)
7434481Sbholler
7444481Sbholler#endif	/* __i386 */
7454481Sbholler#endif	/* __lint */
7464481Sbholler
7474481Sbholler#if defined(__lint)
7484481Sbholler
7494481Sbholler/*ARGSUSED*/
7504481Sbhollervoid
7514481Sbholleri86_mwait(uint32_t data, uint32_t extensions)
7529489SJoe.Bonasera@sun.com{}
7534481Sbholler
7544481Sbholler#else	/* __lint */
7554481Sbholler
7564481Sbholler#if defined(__amd64)
7574481Sbholler
7584481Sbholler	ENTRY_NP(i86_mwait)
7594481Sbholler	pushq	%rbp
7604481Sbholler	movq	%rsp, %rbp
7614481Sbholler	movq	%rdi, %rax		/* data */
7624481Sbholler	movq	%rsi, %rcx		/* extensions */
7634481Sbholler	.byte	0x0f, 0x01, 0xc9	/* mwait */
7644481Sbholler	leave
7654481Sbholler	ret
7664481Sbholler	SET_SIZE(i86_mwait)
7674481Sbholler
7684481Sbholler#elif defined(__i386)
7694481Sbholler
7704481Sbholler	ENTRY_NP(i86_mwait)
7714481Sbholler	pushl	%ebp
7724481Sbholler	movl	%esp, %ebp
7734501Sbholler	movl	0x8(%ebp),%eax		/* data */
7744501Sbholler	movl	0xc(%ebp),%ecx		/* extensions */
7754481Sbholler	.byte	0x0f, 0x01, 0xc9	/* mwait */
7764481Sbholler	leave
7774481Sbholler	ret
7784481Sbholler	SET_SIZE(i86_mwait)
7794481Sbholler
7804481Sbholler#endif	/* __i386 */
7814481Sbholler#endif	/* __lint */
7823446Smrj
7839489SJoe.Bonasera@sun.com#if defined(__xpv)
7849489SJoe.Bonasera@sun.com	/*
7859489SJoe.Bonasera@sun.com	 * Defined in C
7869489SJoe.Bonasera@sun.com	 */
7879489SJoe.Bonasera@sun.com#else
7889489SJoe.Bonasera@sun.com
7893446Smrj#if defined(__lint)
7903446Smrj
7913446Smrjhrtime_t
7923446Smrjtsc_read(void)
7933446Smrj{
7943446Smrj	return (0);
7953446Smrj}
7963446Smrj
7973446Smrj#else	/* __lint */
7983446Smrj
7995084Sjohnlev#if defined(__amd64)
8005084Sjohnlev
8013446Smrj	ENTRY_NP(tsc_read)
8025322Ssudheer	movq	%rbx, %r11
8035322Ssudheer	movl	$0, %eax
8045322Ssudheer	cpuid
8055322Ssudheer	rdtsc
8065322Ssudheer	movq	%r11, %rbx
8075322Ssudheer	shlq	$32, %rdx
8085322Ssudheer	orq	%rdx, %rax
8095322Ssudheer	ret
8105322Ssudheer	.globl _tsc_mfence_start
8115322Ssudheer_tsc_mfence_start:
8125322Ssudheer	mfence
8133446Smrj	rdtsc
8143446Smrj	shlq	$32, %rdx
8153446Smrj	orq	%rdx, %rax
8163446Smrj	ret
8175322Ssudheer	.globl _tsc_mfence_end
8185322Ssudheer_tsc_mfence_end:
8195322Ssudheer	.globl _tscp_start
8205322Ssudheer_tscp_start:
8215322Ssudheer	.byte	0x0f, 0x01, 0xf9	/* rdtscp instruction */
8225322Ssudheer	shlq	$32, %rdx
8235322Ssudheer	orq	%rdx, %rax
8245322Ssudheer	ret
8255322Ssudheer	.globl _tscp_end
8265322Ssudheer_tscp_end:
8275322Ssudheer	.globl _no_rdtsc_start
8285322Ssudheer_no_rdtsc_start:
8295322Ssudheer	xorl	%edx, %edx
8305322Ssudheer	xorl	%eax, %eax
8315322Ssudheer	ret
8325322Ssudheer	.globl _no_rdtsc_end
8335322Ssudheer_no_rdtsc_end:
8346642Ssudheer	.globl _tsc_lfence_start
8356642Ssudheer_tsc_lfence_start:
8366642Ssudheer	lfence
8376642Ssudheer	rdtsc
8386642Ssudheer	shlq	$32, %rdx
8396642Ssudheer	orq	%rdx, %rax
8406642Ssudheer	ret
8416642Ssudheer	.globl _tsc_lfence_end
8426642Ssudheer_tsc_lfence_end:
8433446Smrj	SET_SIZE(tsc_read)
8443446Smrj
8455322Ssudheer#else /* __i386 */
8465084Sjohnlev
8475084Sjohnlev	ENTRY_NP(tsc_read)
8485322Ssudheer	pushl	%ebx
8495322Ssudheer	movl	$0, %eax
8505322Ssudheer	cpuid
8515322Ssudheer	rdtsc
8525322Ssudheer	popl	%ebx
8535322Ssudheer	ret
8545322Ssudheer	.globl _tsc_mfence_start
8555322Ssudheer_tsc_mfence_start:
8565322Ssudheer	mfence
8575322Ssudheer	rdtsc
8585322Ssudheer	ret
8595322Ssudheer	.globl _tsc_mfence_end
8605322Ssudheer_tsc_mfence_end:
8615322Ssudheer	.globl	_tscp_start
8625322Ssudheer_tscp_start:
8635322Ssudheer	.byte	0x0f, 0x01, 0xf9	/* rdtscp instruction */
8645322Ssudheer	ret
8655322Ssudheer	.globl _tscp_end
8665322Ssudheer_tscp_end:
8675322Ssudheer	.globl _no_rdtsc_start
8685322Ssudheer_no_rdtsc_start:
8695084Sjohnlev	xorl	%edx, %edx
8705322Ssudheer	xorl	%eax, %eax
8715084Sjohnlev	ret
8725322Ssudheer	.globl _no_rdtsc_end
8735322Ssudheer_no_rdtsc_end:
8746642Ssudheer	.globl _tsc_lfence_start
8756642Ssudheer_tsc_lfence_start:
8766642Ssudheer	lfence
8776642Ssudheer	rdtsc
8786642Ssudheer	ret
8796642Ssudheer	.globl _tsc_lfence_end
8806642Ssudheer_tsc_lfence_end:
8815084Sjohnlev	SET_SIZE(tsc_read)
8825084Sjohnlev
8835322Ssudheer#endif	/* __i386 */
8845084Sjohnlev
8853446Smrj#endif	/* __lint */
8863446Smrj
8876880Sdv142724
8885084Sjohnlev#endif	/* __xpv */
8895084Sjohnlev
8906880Sdv142724#ifdef __lint
8916880Sdv142724/*
8926880Sdv142724 * Do not use this function for obtaining clock tick.  This
8936880Sdv142724 * is called by callers who do not need to have a guarenteed
8946880Sdv142724 * correct tick value.  The proper routine to use is tsc_read().
8956880Sdv142724 */
89612908SPavel.Tatashin@Sun.COMu_longlong_t
8976880Sdv142724randtick(void)
8986880Sdv142724{
8996880Sdv142724	return (0);
9006880Sdv142724}
9016880Sdv142724#else
9026880Sdv142724#if defined(__amd64)
9036880Sdv142724	ENTRY_NP(randtick)
9046880Sdv142724	rdtsc
9056880Sdv142724	shlq    $32, %rdx
9066880Sdv142724	orq     %rdx, %rax
9076880Sdv142724	ret
9086880Sdv142724	SET_SIZE(randtick)
9096880Sdv142724#else
9106880Sdv142724	ENTRY_NP(randtick)
9116880Sdv142724	rdtsc
9126880Sdv142724	ret
9136880Sdv142724	SET_SIZE(randtick)
9146880Sdv142724#endif /* __i386 */
9156880Sdv142724#endif /* __lint */
9160Sstevel@tonic-gate/*
9170Sstevel@tonic-gate * Insert entryp after predp in a doubly linked list.
9180Sstevel@tonic-gate */
9190Sstevel@tonic-gate
9200Sstevel@tonic-gate#if defined(__lint)
9210Sstevel@tonic-gate
9220Sstevel@tonic-gate/*ARGSUSED*/
9230Sstevel@tonic-gatevoid
9240Sstevel@tonic-gate_insque(caddr_t entryp, caddr_t predp)
9250Sstevel@tonic-gate{}
9260Sstevel@tonic-gate
9270Sstevel@tonic-gate#else	/* __lint */
9280Sstevel@tonic-gate
9290Sstevel@tonic-gate#if defined(__amd64)
9300Sstevel@tonic-gate
9310Sstevel@tonic-gate	ENTRY(_insque)
9327421SDaniel.Anderson@Sun.COM	movq	(%rsi), %rax		/* predp->forw			*/
9330Sstevel@tonic-gate	movq	%rsi, CPTRSIZE(%rdi)	/* entryp->back = predp		*/
9340Sstevel@tonic-gate	movq	%rax, (%rdi)		/* entryp->forw = predp->forw	*/
9350Sstevel@tonic-gate	movq	%rdi, (%rsi)		/* predp->forw = entryp		*/
9360Sstevel@tonic-gate	movq	%rdi, CPTRSIZE(%rax)	/* predp->forw->back = entryp	*/
9370Sstevel@tonic-gate	ret
9380Sstevel@tonic-gate	SET_SIZE(_insque)
9390Sstevel@tonic-gate
9400Sstevel@tonic-gate#elif defined(__i386)
9410Sstevel@tonic-gate
9420Sstevel@tonic-gate	ENTRY(_insque)
9430Sstevel@tonic-gate	movl	8(%esp), %edx
9440Sstevel@tonic-gate	movl	4(%esp), %ecx
9450Sstevel@tonic-gate	movl	(%edx), %eax		/* predp->forw			*/
9460Sstevel@tonic-gate	movl	%edx, CPTRSIZE(%ecx)	/* entryp->back = predp		*/
9470Sstevel@tonic-gate	movl	%eax, (%ecx)		/* entryp->forw = predp->forw	*/
9480Sstevel@tonic-gate	movl	%ecx, (%edx)		/* predp->forw = entryp		*/
9490Sstevel@tonic-gate	movl	%ecx, CPTRSIZE(%eax)	/* predp->forw->back = entryp	*/
9500Sstevel@tonic-gate	ret
9510Sstevel@tonic-gate	SET_SIZE(_insque)
9520Sstevel@tonic-gate
9530Sstevel@tonic-gate#endif	/* __i386 */
9540Sstevel@tonic-gate#endif	/* __lint */
9550Sstevel@tonic-gate
9560Sstevel@tonic-gate/*
9570Sstevel@tonic-gate * Remove entryp from a doubly linked list
9580Sstevel@tonic-gate */
9590Sstevel@tonic-gate
9600Sstevel@tonic-gate#if defined(__lint)
9610Sstevel@tonic-gate
9620Sstevel@tonic-gate/*ARGSUSED*/
9630Sstevel@tonic-gatevoid
9640Sstevel@tonic-gate_remque(caddr_t entryp)
9650Sstevel@tonic-gate{}
9660Sstevel@tonic-gate
9670Sstevel@tonic-gate#else	/* __lint */
9680Sstevel@tonic-gate
9690Sstevel@tonic-gate#if defined(__amd64)
9700Sstevel@tonic-gate
9710Sstevel@tonic-gate	ENTRY(_remque)
9720Sstevel@tonic-gate	movq	(%rdi), %rax		/* entry->forw */
9730Sstevel@tonic-gate	movq	CPTRSIZE(%rdi), %rdx	/* entry->back */
9740Sstevel@tonic-gate	movq	%rax, (%rdx)		/* entry->back->forw = entry->forw */
9750Sstevel@tonic-gate	movq	%rdx, CPTRSIZE(%rax)	/* entry->forw->back = entry->back */
9760Sstevel@tonic-gate	ret
9770Sstevel@tonic-gate	SET_SIZE(_remque)
9780Sstevel@tonic-gate
9790Sstevel@tonic-gate#elif defined(__i386)
9800Sstevel@tonic-gate
9810Sstevel@tonic-gate	ENTRY(_remque)
9820Sstevel@tonic-gate	movl	4(%esp), %ecx
9830Sstevel@tonic-gate	movl	(%ecx), %eax		/* entry->forw */
9840Sstevel@tonic-gate	movl	CPTRSIZE(%ecx), %edx	/* entry->back */
9850Sstevel@tonic-gate	movl	%eax, (%edx)		/* entry->back->forw = entry->forw */
9860Sstevel@tonic-gate	movl	%edx, CPTRSIZE(%eax)	/* entry->forw->back = entry->back */
9870Sstevel@tonic-gate	ret
9880Sstevel@tonic-gate	SET_SIZE(_remque)
9890Sstevel@tonic-gate
9900Sstevel@tonic-gate#endif	/* __i386 */
9910Sstevel@tonic-gate#endif	/* __lint */
9920Sstevel@tonic-gate
9930Sstevel@tonic-gate/*
9940Sstevel@tonic-gate * Returns the number of
9950Sstevel@tonic-gate * non-NULL bytes in string argument.
9960Sstevel@tonic-gate */
9970Sstevel@tonic-gate
9980Sstevel@tonic-gate#if defined(__lint)
9990Sstevel@tonic-gate
10000Sstevel@tonic-gate/* ARGSUSED */
10010Sstevel@tonic-gatesize_t
10020Sstevel@tonic-gatestrlen(const char *str)
10030Sstevel@tonic-gate{ return (0); }
10040Sstevel@tonic-gate
10050Sstevel@tonic-gate#else	/* __lint */
10060Sstevel@tonic-gate
10070Sstevel@tonic-gate#if defined(__amd64)
10080Sstevel@tonic-gate
10090Sstevel@tonic-gate/*
10100Sstevel@tonic-gate * This is close to a simple transliteration of a C version of this
10110Sstevel@tonic-gate * routine.  We should either just -make- this be a C version, or
10120Sstevel@tonic-gate * justify having it in assembler by making it significantly faster.
10130Sstevel@tonic-gate *
10140Sstevel@tonic-gate * size_t
10150Sstevel@tonic-gate * strlen(const char *s)
10160Sstevel@tonic-gate * {
10170Sstevel@tonic-gate *	const char *s0;
10180Sstevel@tonic-gate * #if defined(DEBUG)
10190Sstevel@tonic-gate *	if ((uintptr_t)s < KERNELBASE)
10200Sstevel@tonic-gate *		panic(.str_panic_msg);
10210Sstevel@tonic-gate * #endif
10220Sstevel@tonic-gate *	for (s0 = s; *s; s++)
10230Sstevel@tonic-gate *		;
10240Sstevel@tonic-gate *	return (s - s0);
10250Sstevel@tonic-gate * }
10260Sstevel@tonic-gate */
10270Sstevel@tonic-gate
10280Sstevel@tonic-gate	ENTRY(strlen)
10290Sstevel@tonic-gate#ifdef DEBUG
10303446Smrj	movq	postbootkernelbase(%rip), %rax
10310Sstevel@tonic-gate	cmpq	%rax, %rdi
10320Sstevel@tonic-gate	jae	str_valid
10330Sstevel@tonic-gate	pushq	%rbp
10340Sstevel@tonic-gate	movq	%rsp, %rbp
10350Sstevel@tonic-gate	leaq	.str_panic_msg(%rip), %rdi
10360Sstevel@tonic-gate	xorl	%eax, %eax
10370Sstevel@tonic-gate	call	panic
10380Sstevel@tonic-gate#endif	/* DEBUG */
10390Sstevel@tonic-gatestr_valid:
10400Sstevel@tonic-gate	cmpb	$0, (%rdi)
10410Sstevel@tonic-gate	movq	%rdi, %rax
10420Sstevel@tonic-gate	je	.null_found
10430Sstevel@tonic-gate	.align	4
10440Sstevel@tonic-gate.strlen_loop:
10450Sstevel@tonic-gate	incq	%rdi
10460Sstevel@tonic-gate	cmpb	$0, (%rdi)
10470Sstevel@tonic-gate	jne	.strlen_loop
10480Sstevel@tonic-gate.null_found:
10490Sstevel@tonic-gate	subq	%rax, %rdi
10500Sstevel@tonic-gate	movq	%rdi, %rax
10510Sstevel@tonic-gate	ret
10520Sstevel@tonic-gate	SET_SIZE(strlen)
10530Sstevel@tonic-gate
10540Sstevel@tonic-gate#elif defined(__i386)
10550Sstevel@tonic-gate
10560Sstevel@tonic-gate	ENTRY(strlen)
10570Sstevel@tonic-gate#ifdef DEBUG
10583446Smrj	movl	postbootkernelbase, %eax
10590Sstevel@tonic-gate	cmpl	%eax, 4(%esp)
10600Sstevel@tonic-gate	jae	str_valid
10610Sstevel@tonic-gate	pushl	%ebp
10620Sstevel@tonic-gate	movl	%esp, %ebp
10630Sstevel@tonic-gate	pushl	$.str_panic_msg
10640Sstevel@tonic-gate	call	panic
10650Sstevel@tonic-gate#endif /* DEBUG */
10660Sstevel@tonic-gate
10670Sstevel@tonic-gatestr_valid:
10680Sstevel@tonic-gate	movl	4(%esp), %eax		/* %eax = string address */
10690Sstevel@tonic-gate	testl	$3, %eax		/* if %eax not word aligned */
10700Sstevel@tonic-gate	jnz	.not_word_aligned	/* goto .not_word_aligned */
10710Sstevel@tonic-gate	.align	4
10720Sstevel@tonic-gate.word_aligned:
10730Sstevel@tonic-gate	movl	(%eax), %edx		/* move 1 word from (%eax) to %edx */
10740Sstevel@tonic-gate	movl	$0x7f7f7f7f, %ecx
10750Sstevel@tonic-gate	andl	%edx, %ecx		/* %ecx = %edx & 0x7f7f7f7f */
10760Sstevel@tonic-gate	addl	$4, %eax		/* next word */
10770Sstevel@tonic-gate	addl	$0x7f7f7f7f, %ecx	/* %ecx += 0x7f7f7f7f */
10780Sstevel@tonic-gate	orl	%edx, %ecx		/* %ecx |= %edx */
10790Sstevel@tonic-gate	andl	$0x80808080, %ecx	/* %ecx &= 0x80808080 */
10800Sstevel@tonic-gate	cmpl	$0x80808080, %ecx	/* if no null byte in this word */
10810Sstevel@tonic-gate	je	.word_aligned		/* goto .word_aligned */
10820Sstevel@tonic-gate	subl	$4, %eax		/* post-incremented */
10830Sstevel@tonic-gate.not_word_aligned:
10840Sstevel@tonic-gate	cmpb	$0, (%eax)		/* if a byte in (%eax) is null */
10850Sstevel@tonic-gate	je	.null_found		/* goto .null_found */
10860Sstevel@tonic-gate	incl	%eax			/* next byte */
10870Sstevel@tonic-gate	testl	$3, %eax		/* if %eax not word aligned */
10880Sstevel@tonic-gate	jnz	.not_word_aligned	/* goto .not_word_aligned */
10890Sstevel@tonic-gate	jmp	.word_aligned		/* goto .word_aligned */
10900Sstevel@tonic-gate	.align	4
10910Sstevel@tonic-gate.null_found:
10920Sstevel@tonic-gate	subl	4(%esp), %eax		/* %eax -= string address */
10930Sstevel@tonic-gate	ret
10940Sstevel@tonic-gate	SET_SIZE(strlen)
10950Sstevel@tonic-gate
10960Sstevel@tonic-gate#endif	/* __i386 */
10970Sstevel@tonic-gate
10980Sstevel@tonic-gate#ifdef DEBUG
10990Sstevel@tonic-gate	.text
11000Sstevel@tonic-gate.str_panic_msg:
11010Sstevel@tonic-gate	.string "strlen: argument below kernelbase"
11020Sstevel@tonic-gate#endif /* DEBUG */
11030Sstevel@tonic-gate
11040Sstevel@tonic-gate#endif	/* __lint */
11050Sstevel@tonic-gate
11060Sstevel@tonic-gate	/*
11077421SDaniel.Anderson@Sun.COM	 * Berkeley 4.3 introduced symbolically named interrupt levels
11080Sstevel@tonic-gate	 * as a way deal with priority in a machine independent fashion.
11090Sstevel@tonic-gate	 * Numbered priorities are machine specific, and should be
11100Sstevel@tonic-gate	 * discouraged where possible.
11110Sstevel@tonic-gate	 *
11120Sstevel@tonic-gate	 * Note, for the machine specific priorities there are
11130Sstevel@tonic-gate	 * examples listed for devices that use a particular priority.
11140Sstevel@tonic-gate	 * It should not be construed that all devices of that
11150Sstevel@tonic-gate	 * type should be at that priority.  It is currently were
11160Sstevel@tonic-gate	 * the current devices fit into the priority scheme based
11170Sstevel@tonic-gate	 * upon time criticalness.
11180Sstevel@tonic-gate	 *
11190Sstevel@tonic-gate	 * The underlying assumption of these assignments is that
11200Sstevel@tonic-gate	 * IPL 10 is the highest level from which a device
11210Sstevel@tonic-gate	 * routine can call wakeup.  Devices that interrupt from higher
11220Sstevel@tonic-gate	 * levels are restricted in what they can do.  If they need
11230Sstevel@tonic-gate	 * kernels services they should schedule a routine at a lower
11240Sstevel@tonic-gate	 * level (via software interrupt) to do the required
11250Sstevel@tonic-gate	 * processing.
11260Sstevel@tonic-gate	 *
11270Sstevel@tonic-gate	 * Examples of this higher usage:
11280Sstevel@tonic-gate	 *	Level	Usage
11290Sstevel@tonic-gate	 *	14	Profiling clock (and PROM uart polling clock)
11300Sstevel@tonic-gate	 *	12	Serial ports
11310Sstevel@tonic-gate	 *
11320Sstevel@tonic-gate	 * The serial ports request lower level processing on level 6.
11330Sstevel@tonic-gate	 *
11340Sstevel@tonic-gate	 * Also, almost all splN routines (where N is a number or a
11350Sstevel@tonic-gate	 * mnemonic) will do a RAISE(), on the assumption that they are
11360Sstevel@tonic-gate	 * never used to lower our priority.
11370Sstevel@tonic-gate	 * The exceptions are:
11380Sstevel@tonic-gate	 *	spl8()		Because you can't be above 15 to begin with!
11390Sstevel@tonic-gate	 *	splzs()		Because this is used at boot time to lower our
11400Sstevel@tonic-gate	 *			priority, to allow the PROM to poll the uart.
11410Sstevel@tonic-gate	 *	spl0()		Used to lower priority to 0.
11420Sstevel@tonic-gate	 */
11430Sstevel@tonic-gate
11440Sstevel@tonic-gate#if defined(__lint)
11450Sstevel@tonic-gate
11460Sstevel@tonic-gateint spl0(void)		{ return (0); }
11470Sstevel@tonic-gateint spl6(void)		{ return (0); }
11480Sstevel@tonic-gateint spl7(void)		{ return (0); }
11490Sstevel@tonic-gateint spl8(void)		{ return (0); }
11500Sstevel@tonic-gateint splhigh(void)	{ return (0); }
11510Sstevel@tonic-gateint splhi(void)		{ return (0); }
11520Sstevel@tonic-gateint splzs(void)		{ return (0); }
11530Sstevel@tonic-gate
11543446Smrj/* ARGSUSED */
11553446Smrjvoid
11563446Smrjsplx(int level)
11573446Smrj{}
11583446Smrj
11590Sstevel@tonic-gate#else	/* __lint */
11600Sstevel@tonic-gate
11610Sstevel@tonic-gate#if defined(__amd64)
11620Sstevel@tonic-gate
11630Sstevel@tonic-gate#define	SETPRI(level) \
11643446Smrj	movl	$/**/level, %edi;	/* new priority */		\
11653446Smrj	jmp	do_splx			/* redirect to do_splx */
11663446Smrj
11673446Smrj#define	RAISE(level) \
11683446Smrj	movl	$/**/level, %edi;	/* new priority */		\
11693446Smrj	jmp	splr			/* redirect to splr */
11700Sstevel@tonic-gate
11710Sstevel@tonic-gate#elif defined(__i386)
11720Sstevel@tonic-gate
11733446Smrj#define	SETPRI(level) \
11743446Smrj	pushl	$/**/level;	/* new priority */			\
11753446Smrj	call	do_splx;	/* invoke common splx code */		\
11763446Smrj	addl	$4, %esp;	/* unstack arg */			\
11773446Smrj	ret
11783446Smrj
11793446Smrj#define	RAISE(level) \
11803446Smrj	pushl	$/**/level;	/* new priority */			\
11813446Smrj	call	splr;		/* invoke common splr code */		\
11823446Smrj	addl	$4, %esp;	/* unstack args */			\
11833446Smrj	ret
11840Sstevel@tonic-gate
11850Sstevel@tonic-gate#endif	/* __i386 */
11860Sstevel@tonic-gate
11870Sstevel@tonic-gate	/* locks out all interrupts, including memory errors */
11880Sstevel@tonic-gate	ENTRY(spl8)
11890Sstevel@tonic-gate	SETPRI(15)
11900Sstevel@tonic-gate	SET_SIZE(spl8)
11910Sstevel@tonic-gate
11920Sstevel@tonic-gate	/* just below the level that profiling runs */
11930Sstevel@tonic-gate	ENTRY(spl7)
11940Sstevel@tonic-gate	RAISE(13)
11950Sstevel@tonic-gate	SET_SIZE(spl7)
11960Sstevel@tonic-gate
11970Sstevel@tonic-gate	/* sun specific - highest priority onboard serial i/o asy ports */
11980Sstevel@tonic-gate	ENTRY(splzs)
11990Sstevel@tonic-gate	SETPRI(12)	/* Can't be a RAISE, as it's used to lower us */
12000Sstevel@tonic-gate	SET_SIZE(splzs)
12010Sstevel@tonic-gate
12020Sstevel@tonic-gate	ENTRY(splhi)
12030Sstevel@tonic-gate	ALTENTRY(splhigh)
12040Sstevel@tonic-gate	ALTENTRY(spl6)
12050Sstevel@tonic-gate	ALTENTRY(i_ddi_splhigh)
12063446Smrj
12073446Smrj	RAISE(DISP_LEVEL)
12080Sstevel@tonic-gate
12090Sstevel@tonic-gate	SET_SIZE(i_ddi_splhigh)
12100Sstevel@tonic-gate	SET_SIZE(spl6)
12110Sstevel@tonic-gate	SET_SIZE(splhigh)
12120Sstevel@tonic-gate	SET_SIZE(splhi)
12130Sstevel@tonic-gate
12140Sstevel@tonic-gate	/* allow all interrupts */
12150Sstevel@tonic-gate	ENTRY(spl0)
12160Sstevel@tonic-gate	SETPRI(0)
12170Sstevel@tonic-gate	SET_SIZE(spl0)
12180Sstevel@tonic-gate
12193446Smrj
12207421SDaniel.Anderson@Sun.COM	/* splx implementation */
12210Sstevel@tonic-gate	ENTRY(splx)
12223446Smrj	jmp	do_splx		/* redirect to common splx code */
12230Sstevel@tonic-gate	SET_SIZE(splx)
12240Sstevel@tonic-gate
12250Sstevel@tonic-gate#endif	/* __lint */
12260Sstevel@tonic-gate
12270Sstevel@tonic-gate#if defined(__i386)
12280Sstevel@tonic-gate
12290Sstevel@tonic-gate/*
12300Sstevel@tonic-gate * Read and write the %gs register
12310Sstevel@tonic-gate */
12320Sstevel@tonic-gate
12330Sstevel@tonic-gate#if defined(__lint)
12340Sstevel@tonic-gate
12350Sstevel@tonic-gate/*ARGSUSED*/
12360Sstevel@tonic-gateuint16_t
12370Sstevel@tonic-gategetgs(void)
12380Sstevel@tonic-gate{ return (0); }
12390Sstevel@tonic-gate
12400Sstevel@tonic-gate/*ARGSUSED*/
12410Sstevel@tonic-gatevoid
12420Sstevel@tonic-gatesetgs(uint16_t sel)
12430Sstevel@tonic-gate{}
12440Sstevel@tonic-gate
12450Sstevel@tonic-gate#else	/* __lint */
12460Sstevel@tonic-gate
12470Sstevel@tonic-gate	ENTRY(getgs)
12480Sstevel@tonic-gate	clr	%eax
12490Sstevel@tonic-gate	movw	%gs, %ax
12500Sstevel@tonic-gate	ret
12510Sstevel@tonic-gate	SET_SIZE(getgs)
12520Sstevel@tonic-gate
12530Sstevel@tonic-gate	ENTRY(setgs)
12540Sstevel@tonic-gate	movw	4(%esp), %gs
12550Sstevel@tonic-gate	ret
12560Sstevel@tonic-gate	SET_SIZE(setgs)
12570Sstevel@tonic-gate
12580Sstevel@tonic-gate#endif	/* __lint */
12590Sstevel@tonic-gate#endif	/* __i386 */
12600Sstevel@tonic-gate
12610Sstevel@tonic-gate#if defined(__lint)
12620Sstevel@tonic-gate
12630Sstevel@tonic-gatevoid
12640Sstevel@tonic-gatepc_reset(void)
12650Sstevel@tonic-gate{}
12660Sstevel@tonic-gate
12672866Sszhouvoid
12682866Sszhouefi_reset(void)
12692866Sszhou{}
12702866Sszhou
12710Sstevel@tonic-gate#else	/* __lint */
12720Sstevel@tonic-gate
12731072Ssethg	ENTRY(wait_500ms)
12749291SGeorge.Vasick@Sun.COM#if defined(__amd64)
12759291SGeorge.Vasick@Sun.COM	pushq	%rbx
12769291SGeorge.Vasick@Sun.COM#elif defined(__i386)
12771176Ssethg	push	%ebx
12789291SGeorge.Vasick@Sun.COM#endif
12791176Ssethg	movl	$50000, %ebx
12801072Ssethg1:
12811072Ssethg	call	tenmicrosec
12821176Ssethg	decl	%ebx
12831176Ssethg	jnz	1b
12849291SGeorge.Vasick@Sun.COM#if defined(__amd64)
12859291SGeorge.Vasick@Sun.COM	popq	%rbx
12869291SGeorge.Vasick@Sun.COM#elif defined(__i386)
12871176Ssethg	pop	%ebx
12889291SGeorge.Vasick@Sun.COM#endif
12891072Ssethg	ret
12901072Ssethg	SET_SIZE(wait_500ms)
12911072Ssethg
12921072Ssethg#define	RESET_METHOD_KBC	1
12931072Ssethg#define	RESET_METHOD_PORT92	2
12941072Ssethg#define RESET_METHOD_PCI	4
12951072Ssethg
12961072Ssethg	DGDEF3(pc_reset_methods, 4, 8)
12971072Ssethg	.long RESET_METHOD_KBC|RESET_METHOD_PORT92|RESET_METHOD_PCI;
12981072Ssethg
12990Sstevel@tonic-gate	ENTRY(pc_reset)
13001072Ssethg
13011176Ssethg#if defined(__i386)
13021072Ssethg	testl	$RESET_METHOD_KBC, pc_reset_methods
13031176Ssethg#elif defined(__amd64)
13041176Ssethg	testl	$RESET_METHOD_KBC, pc_reset_methods(%rip)
13051176Ssethg#endif
13061072Ssethg	jz	1f
13071072Ssethg
1308886Ssethg	/
1309886Ssethg	/ Try the classic keyboard controller-triggered reset.
1310886Ssethg	/
13110Sstevel@tonic-gate	movw	$0x64, %dx
13120Sstevel@tonic-gate	movb	$0xfe, %al
13130Sstevel@tonic-gate	outb	(%dx)
1314886Ssethg
13151072Ssethg	/ Wait up to 500 milliseconds here for the keyboard controller
13161072Ssethg	/ to pull the reset line.  On some systems where the keyboard
13171072Ssethg	/ controller is slow to pull the reset line, the next reset method
13181072Ssethg	/ may be executed (which may be bad if those systems hang when the
13191072Ssethg	/ next reset method is used, e.g. Ferrari 3400 (doesn't like port 92),
13201072Ssethg	/ and Ferrari 4000 (doesn't like the cf9 reset method))
13211072Ssethg
13221072Ssethg	call	wait_500ms
13231072Ssethg
13241072Ssethg1:
13251176Ssethg#if defined(__i386)
13261072Ssethg	testl	$RESET_METHOD_PORT92, pc_reset_methods
13271176Ssethg#elif defined(__amd64)
13281176Ssethg	testl	$RESET_METHOD_PORT92, pc_reset_methods(%rip)
13291176Ssethg#endif
13301072Ssethg	jz	3f
13311072Ssethg
1332886Ssethg	/
1333886Ssethg	/ Try port 0x92 fast reset
1334886Ssethg	/
1335886Ssethg	movw	$0x92, %dx
1336886Ssethg	inb	(%dx)
1337886Ssethg	cmpb	$0xff, %al	/ If port's not there, we should get back 0xFF
1338886Ssethg	je	1f
1339886Ssethg	testb	$1, %al		/ If bit 0
1340886Ssethg	jz	2f		/ is clear, jump to perform the reset
1341886Ssethg	andb	$0xfe, %al	/ otherwise,
1342886Ssethg	outb	(%dx)		/ clear bit 0 first, then
1343886Ssethg2:
1344886Ssethg	orb	$1, %al		/ Set bit 0
1345886Ssethg	outb	(%dx)		/ and reset the system
1346886Ssethg1:
1347985Ssethg
13481072Ssethg	call	wait_500ms
13491072Ssethg
13501072Ssethg3:
13511176Ssethg#if defined(__i386)
13521072Ssethg	testl	$RESET_METHOD_PCI, pc_reset_methods
13531176Ssethg#elif defined(__amd64)
13541176Ssethg	testl	$RESET_METHOD_PCI, pc_reset_methods(%rip)
13551176Ssethg#endif
13561072Ssethg	jz	4f
13571072Ssethg
1358985Ssethg	/ Try the PCI (soft) reset vector (should work on all modern systems,
1359985Ssethg	/ but has been shown to cause problems on 450NX systems, and some newer
1360985Ssethg	/ systems (e.g. ATI IXP400-equipped systems))
1361985Ssethg	/ When resetting via this method, 2 writes are required.  The first
1362985Ssethg	/ targets bit 1 (0=hard reset without power cycle, 1=hard reset with
1363985Ssethg	/ power cycle).
1364985Ssethg	/ The reset occurs on the second write, during bit 2's transition from
1365985Ssethg	/ 0->1.
1366985Ssethg	movw	$0xcf9, %dx
1367985Ssethg	movb	$0x2, %al	/ Reset mode = hard, no power cycle
1368985Ssethg	outb	(%dx)
1369985Ssethg	movb	$0x6, %al
1370985Ssethg	outb	(%dx)
1371985Ssethg
13721072Ssethg	call	wait_500ms
13731072Ssethg
13741072Ssethg4:
1375886Ssethg	/
1376985Ssethg	/ port 0xcf9 failed also.  Last-ditch effort is to
1377886Ssethg	/ triple-fault the CPU.
13782866Sszhou	/ Also, use triple fault for EFI firmware
1379886Ssethg	/
13802866Sszhou	ENTRY(efi_reset)
1381886Ssethg#if defined(__amd64)
1382886Ssethg	pushq	$0x0
1383886Ssethg	pushq	$0x0		/ IDT base of 0, limit of 0 + 2 unused bytes
1384886Ssethg	lidt	(%rsp)
1385886Ssethg#elif defined(__i386)
1386886Ssethg	pushl	$0x0
1387886Ssethg	pushl	$0x0		/ IDT base of 0, limit of 0 + 2 unused bytes
1388886Ssethg	lidt	(%esp)
1389886Ssethg#endif
1390886Ssethg	int	$0x0		/ Trigger interrupt, generate triple-fault
13911072Ssethg
13921072Ssethg	cli
13931072Ssethg	hlt			/ Wait forever
13940Sstevel@tonic-gate	/*NOTREACHED*/
13952866Sszhou	SET_SIZE(efi_reset)
13960Sstevel@tonic-gate	SET_SIZE(pc_reset)
13970Sstevel@tonic-gate
13980Sstevel@tonic-gate#endif	/* __lint */
13990Sstevel@tonic-gate
14000Sstevel@tonic-gate/*
14010Sstevel@tonic-gate * C callable in and out routines
14020Sstevel@tonic-gate */
14030Sstevel@tonic-gate
14040Sstevel@tonic-gate#if defined(__lint)
14050Sstevel@tonic-gate
14060Sstevel@tonic-gate/* ARGSUSED */
14070Sstevel@tonic-gatevoid
14080Sstevel@tonic-gateoutl(int port_address, uint32_t val)
14090Sstevel@tonic-gate{}
14100Sstevel@tonic-gate
14110Sstevel@tonic-gate#else	/* __lint */
14120Sstevel@tonic-gate
14130Sstevel@tonic-gate#if defined(__amd64)
14140Sstevel@tonic-gate
14150Sstevel@tonic-gate	ENTRY(outl)
14160Sstevel@tonic-gate	movw	%di, %dx
14170Sstevel@tonic-gate	movl	%esi, %eax
14180Sstevel@tonic-gate	outl	(%dx)
14190Sstevel@tonic-gate	ret
14200Sstevel@tonic-gate	SET_SIZE(outl)
14210Sstevel@tonic-gate
14220Sstevel@tonic-gate#elif defined(__i386)
14230Sstevel@tonic-gate
14240Sstevel@tonic-gate	.set	PORT, 4
14250Sstevel@tonic-gate	.set	VAL, 8
14260Sstevel@tonic-gate
14270Sstevel@tonic-gate	ENTRY(outl)
14280Sstevel@tonic-gate	movw	PORT(%esp), %dx
14290Sstevel@tonic-gate	movl	VAL(%esp), %eax
14300Sstevel@tonic-gate	outl	(%dx)
14310Sstevel@tonic-gate	ret
14320Sstevel@tonic-gate	SET_SIZE(outl)
14330Sstevel@tonic-gate
14340Sstevel@tonic-gate#endif	/* __i386 */
14350Sstevel@tonic-gate#endif	/* __lint */
14360Sstevel@tonic-gate
14370Sstevel@tonic-gate#if defined(__lint)
14380Sstevel@tonic-gate
14390Sstevel@tonic-gate/* ARGSUSED */
14400Sstevel@tonic-gatevoid
14410Sstevel@tonic-gateoutw(int port_address, uint16_t val)
14420Sstevel@tonic-gate{}
14430Sstevel@tonic-gate
14440Sstevel@tonic-gate#else	/* __lint */
14450Sstevel@tonic-gate
14460Sstevel@tonic-gate#if defined(__amd64)
14470Sstevel@tonic-gate
14480Sstevel@tonic-gate	ENTRY(outw)
14490Sstevel@tonic-gate	movw	%di, %dx
14500Sstevel@tonic-gate	movw	%si, %ax
14510Sstevel@tonic-gate	D16 outl (%dx)		/* XX64 why not outw? */
14520Sstevel@tonic-gate	ret
14530Sstevel@tonic-gate	SET_SIZE(outw)
14540Sstevel@tonic-gate
14550Sstevel@tonic-gate#elif defined(__i386)
14560Sstevel@tonic-gate
14570Sstevel@tonic-gate	ENTRY(outw)
14580Sstevel@tonic-gate	movw	PORT(%esp), %dx
14590Sstevel@tonic-gate	movw	VAL(%esp), %ax
14600Sstevel@tonic-gate	D16 outl (%dx)
14610Sstevel@tonic-gate	ret
14620Sstevel@tonic-gate	SET_SIZE(outw)
14630Sstevel@tonic-gate
14640Sstevel@tonic-gate#endif	/* __i386 */
14650Sstevel@tonic-gate#endif	/* __lint */
14660Sstevel@tonic-gate
14670Sstevel@tonic-gate#if defined(__lint)
14680Sstevel@tonic-gate
14690Sstevel@tonic-gate/* ARGSUSED */
14700Sstevel@tonic-gatevoid
14710Sstevel@tonic-gateoutb(int port_address, uint8_t val)
14720Sstevel@tonic-gate{}
14730Sstevel@tonic-gate
14740Sstevel@tonic-gate#else	/* __lint */
14750Sstevel@tonic-gate
14760Sstevel@tonic-gate#if defined(__amd64)
14770Sstevel@tonic-gate
14780Sstevel@tonic-gate	ENTRY(outb)
14790Sstevel@tonic-gate	movw	%di, %dx
14800Sstevel@tonic-gate	movb	%sil, %al
14810Sstevel@tonic-gate	outb	(%dx)
14820Sstevel@tonic-gate	ret
14830Sstevel@tonic-gate	SET_SIZE(outb)
14840Sstevel@tonic-gate
14850Sstevel@tonic-gate#elif defined(__i386)
14860Sstevel@tonic-gate
14870Sstevel@tonic-gate	ENTRY(outb)
14880Sstevel@tonic-gate	movw	PORT(%esp), %dx
14890Sstevel@tonic-gate	movb	VAL(%esp), %al
14900Sstevel@tonic-gate	outb	(%dx)
14910Sstevel@tonic-gate	ret
14920Sstevel@tonic-gate	SET_SIZE(outb)
14930Sstevel@tonic-gate
14940Sstevel@tonic-gate#endif	/* __i386 */
14950Sstevel@tonic-gate#endif	/* __lint */
14960Sstevel@tonic-gate
14970Sstevel@tonic-gate#if defined(__lint)
14980Sstevel@tonic-gate
14990Sstevel@tonic-gate/* ARGSUSED */
15000Sstevel@tonic-gateuint32_t
15010Sstevel@tonic-gateinl(int port_address)
15020Sstevel@tonic-gate{ return (0); }
15030Sstevel@tonic-gate
15040Sstevel@tonic-gate#else	/* __lint */
15050Sstevel@tonic-gate
15060Sstevel@tonic-gate#if defined(__amd64)
15070Sstevel@tonic-gate
15080Sstevel@tonic-gate	ENTRY(inl)
15090Sstevel@tonic-gate	xorl	%eax, %eax
15100Sstevel@tonic-gate	movw	%di, %dx
15110Sstevel@tonic-gate	inl	(%dx)
15120Sstevel@tonic-gate	ret
15130Sstevel@tonic-gate	SET_SIZE(inl)
15140Sstevel@tonic-gate
15150Sstevel@tonic-gate#elif defined(__i386)
15160Sstevel@tonic-gate
15170Sstevel@tonic-gate	ENTRY(inl)
15180Sstevel@tonic-gate	movw	PORT(%esp), %dx
15190Sstevel@tonic-gate	inl	(%dx)
15200Sstevel@tonic-gate	ret
15210Sstevel@tonic-gate	SET_SIZE(inl)
15220Sstevel@tonic-gate
15230Sstevel@tonic-gate#endif	/* __i386 */
15240Sstevel@tonic-gate#endif	/* __lint */
15250Sstevel@tonic-gate
15260Sstevel@tonic-gate#if defined(__lint)
15270Sstevel@tonic-gate
15280Sstevel@tonic-gate/* ARGSUSED */
15290Sstevel@tonic-gateuint16_t
15300Sstevel@tonic-gateinw(int port_address)
15310Sstevel@tonic-gate{ return (0); }
15320Sstevel@tonic-gate
15330Sstevel@tonic-gate#else	/* __lint */
15340Sstevel@tonic-gate
15350Sstevel@tonic-gate#if defined(__amd64)
15360Sstevel@tonic-gate
15370Sstevel@tonic-gate	ENTRY(inw)
15380Sstevel@tonic-gate	xorl	%eax, %eax
15390Sstevel@tonic-gate	movw	%di, %dx
15400Sstevel@tonic-gate	D16 inl	(%dx)
15410Sstevel@tonic-gate	ret
15420Sstevel@tonic-gate	SET_SIZE(inw)
15430Sstevel@tonic-gate
15440Sstevel@tonic-gate#elif defined(__i386)
15450Sstevel@tonic-gate
15460Sstevel@tonic-gate	ENTRY(inw)
15470Sstevel@tonic-gate	subl	%eax, %eax
15480Sstevel@tonic-gate	movw	PORT(%esp), %dx
15490Sstevel@tonic-gate	D16 inl	(%dx)
15500Sstevel@tonic-gate	ret
15510Sstevel@tonic-gate	SET_SIZE(inw)
15520Sstevel@tonic-gate
15530Sstevel@tonic-gate#endif	/* __i386 */
15540Sstevel@tonic-gate#endif	/* __lint */
15550Sstevel@tonic-gate
15560Sstevel@tonic-gate
15570Sstevel@tonic-gate#if defined(__lint)
15580Sstevel@tonic-gate
15590Sstevel@tonic-gate/* ARGSUSED */
15600Sstevel@tonic-gateuint8_t
15610Sstevel@tonic-gateinb(int port_address)
15620Sstevel@tonic-gate{ return (0); }
15630Sstevel@tonic-gate
15640Sstevel@tonic-gate#else	/* __lint */
15650Sstevel@tonic-gate
15660Sstevel@tonic-gate#if defined(__amd64)
15670Sstevel@tonic-gate
15680Sstevel@tonic-gate	ENTRY(inb)
15690Sstevel@tonic-gate	xorl	%eax, %eax
15700Sstevel@tonic-gate	movw	%di, %dx
15710Sstevel@tonic-gate	inb	(%dx)
15720Sstevel@tonic-gate	ret
15730Sstevel@tonic-gate	SET_SIZE(inb)
15740Sstevel@tonic-gate
15750Sstevel@tonic-gate#elif defined(__i386)
15760Sstevel@tonic-gate
15770Sstevel@tonic-gate	ENTRY(inb)
15780Sstevel@tonic-gate	subl    %eax, %eax
15790Sstevel@tonic-gate	movw	PORT(%esp), %dx
15800Sstevel@tonic-gate	inb	(%dx)
15810Sstevel@tonic-gate	ret
15820Sstevel@tonic-gate	SET_SIZE(inb)
15830Sstevel@tonic-gate
15840Sstevel@tonic-gate#endif	/* __i386 */
15850Sstevel@tonic-gate#endif	/* __lint */
15860Sstevel@tonic-gate
15870Sstevel@tonic-gate
15880Sstevel@tonic-gate#if defined(__lint)
15890Sstevel@tonic-gate
15900Sstevel@tonic-gate/* ARGSUSED */
15910Sstevel@tonic-gatevoid
15920Sstevel@tonic-gaterepoutsw(int port, uint16_t *addr, int cnt)
15930Sstevel@tonic-gate{}
15940Sstevel@tonic-gate
15950Sstevel@tonic-gate#else	/* __lint */
15960Sstevel@tonic-gate
15970Sstevel@tonic-gate#if defined(__amd64)
15980Sstevel@tonic-gate
15990Sstevel@tonic-gate	ENTRY(repoutsw)
16000Sstevel@tonic-gate	movl	%edx, %ecx
16010Sstevel@tonic-gate	movw	%di, %dx
16020Sstevel@tonic-gate	rep
16030Sstevel@tonic-gate	  D16 outsl
16040Sstevel@tonic-gate	ret
16050Sstevel@tonic-gate	SET_SIZE(repoutsw)
16060Sstevel@tonic-gate
16070Sstevel@tonic-gate#elif defined(__i386)
16080Sstevel@tonic-gate
16090Sstevel@tonic-gate	/*
16100Sstevel@tonic-gate	 * The arguments and saved registers are on the stack in the
16110Sstevel@tonic-gate	 *  following order:
16120Sstevel@tonic-gate	 *      |  cnt  |  +16
16130Sstevel@tonic-gate	 *      | *addr |  +12
16140Sstevel@tonic-gate	 *      | port  |  +8
16150Sstevel@tonic-gate	 *      |  eip  |  +4
16160Sstevel@tonic-gate	 *      |  esi  |  <-- %esp
16170Sstevel@tonic-gate	 * If additional values are pushed onto the stack, make sure
16180Sstevel@tonic-gate	 * to adjust the following constants accordingly.
16190Sstevel@tonic-gate	 */
16200Sstevel@tonic-gate	.set	PORT, 8
16210Sstevel@tonic-gate	.set	ADDR, 12
16220Sstevel@tonic-gate	.set	COUNT, 16
16230Sstevel@tonic-gate
16240Sstevel@tonic-gate	ENTRY(repoutsw)
16250Sstevel@tonic-gate	pushl	%esi
16260Sstevel@tonic-gate	movl	PORT(%esp), %edx
16270Sstevel@tonic-gate	movl	ADDR(%esp), %esi
16280Sstevel@tonic-gate	movl	COUNT(%esp), %ecx
16290Sstevel@tonic-gate	rep
16300Sstevel@tonic-gate	  D16 outsl
16310Sstevel@tonic-gate	popl	%esi
16320Sstevel@tonic-gate	ret
16330Sstevel@tonic-gate	SET_SIZE(repoutsw)
16340Sstevel@tonic-gate
16350Sstevel@tonic-gate#endif	/* __i386 */
16360Sstevel@tonic-gate#endif	/* __lint */
16370Sstevel@tonic-gate
16380Sstevel@tonic-gate
16390Sstevel@tonic-gate#if defined(__lint)
16400Sstevel@tonic-gate
16410Sstevel@tonic-gate/* ARGSUSED */
16420Sstevel@tonic-gatevoid
16430Sstevel@tonic-gaterepinsw(int port_addr, uint16_t *addr, int cnt)
16440Sstevel@tonic-gate{}
16450Sstevel@tonic-gate
16460Sstevel@tonic-gate#else	/* __lint */
16470Sstevel@tonic-gate
16480Sstevel@tonic-gate#if defined(__amd64)
16490Sstevel@tonic-gate
16500Sstevel@tonic-gate	ENTRY(repinsw)
16510Sstevel@tonic-gate	movl	%edx, %ecx
16520Sstevel@tonic-gate	movw	%di, %dx
16530Sstevel@tonic-gate	rep
16540Sstevel@tonic-gate	  D16 insl
16550Sstevel@tonic-gate	ret
16560Sstevel@tonic-gate	SET_SIZE(repinsw)
16570Sstevel@tonic-gate
16580Sstevel@tonic-gate#elif defined(__i386)
16590Sstevel@tonic-gate
16600Sstevel@tonic-gate	ENTRY(repinsw)
16610Sstevel@tonic-gate	pushl	%edi
16620Sstevel@tonic-gate	movl	PORT(%esp), %edx
16630Sstevel@tonic-gate	movl	ADDR(%esp), %edi
16640Sstevel@tonic-gate	movl	COUNT(%esp), %ecx
16650Sstevel@tonic-gate	rep
16660Sstevel@tonic-gate	  D16 insl
16670Sstevel@tonic-gate	popl	%edi
16680Sstevel@tonic-gate	ret
16690Sstevel@tonic-gate	SET_SIZE(repinsw)
16700Sstevel@tonic-gate
16710Sstevel@tonic-gate#endif	/* __i386 */
16720Sstevel@tonic-gate#endif	/* __lint */
16730Sstevel@tonic-gate
16740Sstevel@tonic-gate
16750Sstevel@tonic-gate#if defined(__lint)
16760Sstevel@tonic-gate
16770Sstevel@tonic-gate/* ARGSUSED */
16780Sstevel@tonic-gatevoid
16790Sstevel@tonic-gaterepinsb(int port, uint8_t *addr, int count)
16800Sstevel@tonic-gate{}
16810Sstevel@tonic-gate
16820Sstevel@tonic-gate#else	/* __lint */
16830Sstevel@tonic-gate
16840Sstevel@tonic-gate#if defined(__amd64)
16850Sstevel@tonic-gate
16860Sstevel@tonic-gate	ENTRY(repinsb)
16870Sstevel@tonic-gate	movl	%edx, %ecx
16880Sstevel@tonic-gate	movw	%di, %dx
16890Sstevel@tonic-gate	movq	%rsi, %rdi
16900Sstevel@tonic-gate	rep
16910Sstevel@tonic-gate	  insb
16920Sstevel@tonic-gate	ret
16930Sstevel@tonic-gate	SET_SIZE(repinsb)
16940Sstevel@tonic-gate
16950Sstevel@tonic-gate#elif defined(__i386)
16960Sstevel@tonic-gate
16970Sstevel@tonic-gate	/*
16980Sstevel@tonic-gate	 * The arguments and saved registers are on the stack in the
16990Sstevel@tonic-gate	 *  following order:
17000Sstevel@tonic-gate	 *      |  cnt  |  +16
17010Sstevel@tonic-gate	 *      | *addr |  +12
17020Sstevel@tonic-gate	 *      | port  |  +8
17030Sstevel@tonic-gate	 *      |  eip  |  +4
17040Sstevel@tonic-gate	 *      |  esi  |  <-- %esp
17050Sstevel@tonic-gate	 * If additional values are pushed onto the stack, make sure
17060Sstevel@tonic-gate	 * to adjust the following constants accordingly.
17070Sstevel@tonic-gate	 */
17080Sstevel@tonic-gate	.set	IO_PORT, 8
17090Sstevel@tonic-gate	.set	IO_ADDR, 12
17100Sstevel@tonic-gate	.set	IO_COUNT, 16
17110Sstevel@tonic-gate
17120Sstevel@tonic-gate	ENTRY(repinsb)
17130Sstevel@tonic-gate	pushl	%edi
17140Sstevel@tonic-gate	movl	IO_ADDR(%esp), %edi
17150Sstevel@tonic-gate	movl	IO_COUNT(%esp), %ecx
17160Sstevel@tonic-gate	movl	IO_PORT(%esp), %edx
17170Sstevel@tonic-gate	rep
17180Sstevel@tonic-gate	  insb
17190Sstevel@tonic-gate	popl	%edi
17200Sstevel@tonic-gate	ret
17210Sstevel@tonic-gate	SET_SIZE(repinsb)
17220Sstevel@tonic-gate
17230Sstevel@tonic-gate#endif	/* __i386 */
17240Sstevel@tonic-gate#endif	/* __lint */
17250Sstevel@tonic-gate
17260Sstevel@tonic-gate
17270Sstevel@tonic-gate/*
17280Sstevel@tonic-gate * Input a stream of 32-bit words.
17290Sstevel@tonic-gate * NOTE: count is a DWORD count.
17300Sstevel@tonic-gate */
17310Sstevel@tonic-gate#if defined(__lint)
17320Sstevel@tonic-gate
17330Sstevel@tonic-gate/* ARGSUSED */
17340Sstevel@tonic-gatevoid
17350Sstevel@tonic-gaterepinsd(int port, uint32_t *addr, int count)
17360Sstevel@tonic-gate{}
17370Sstevel@tonic-gate
17380Sstevel@tonic-gate#else	/* __lint */
17390Sstevel@tonic-gate
17400Sstevel@tonic-gate#if defined(__amd64)
17410Sstevel@tonic-gate
17420Sstevel@tonic-gate	ENTRY(repinsd)
17430Sstevel@tonic-gate	movl	%edx, %ecx
17440Sstevel@tonic-gate	movw	%di, %dx
17450Sstevel@tonic-gate	movq	%rsi, %rdi
17460Sstevel@tonic-gate	rep
17470Sstevel@tonic-gate	  insl
17480Sstevel@tonic-gate	ret
17490Sstevel@tonic-gate	SET_SIZE(repinsd)
17500Sstevel@tonic-gate
17510Sstevel@tonic-gate#elif defined(__i386)
17520Sstevel@tonic-gate
17530Sstevel@tonic-gate	ENTRY(repinsd)
17540Sstevel@tonic-gate	pushl	%edi
17550Sstevel@tonic-gate	movl	IO_ADDR(%esp), %edi
17560Sstevel@tonic-gate	movl	IO_COUNT(%esp), %ecx
17570Sstevel@tonic-gate	movl	IO_PORT(%esp), %edx
17580Sstevel@tonic-gate	rep
17590Sstevel@tonic-gate	  insl
17600Sstevel@tonic-gate	popl	%edi
17610Sstevel@tonic-gate	ret
17620Sstevel@tonic-gate	SET_SIZE(repinsd)
17630Sstevel@tonic-gate
17640Sstevel@tonic-gate#endif	/* __i386 */
17650Sstevel@tonic-gate#endif	/* __lint */
17660Sstevel@tonic-gate
17670Sstevel@tonic-gate/*
17680Sstevel@tonic-gate * Output a stream of bytes
17690Sstevel@tonic-gate * NOTE: count is a byte count
17700Sstevel@tonic-gate */
17710Sstevel@tonic-gate#if defined(__lint)
17720Sstevel@tonic-gate
17730Sstevel@tonic-gate/* ARGSUSED */
17740Sstevel@tonic-gatevoid
17750Sstevel@tonic-gaterepoutsb(int port, uint8_t *addr, int count)
17760Sstevel@tonic-gate{}
17770Sstevel@tonic-gate
17780Sstevel@tonic-gate#else	/* __lint */
17790Sstevel@tonic-gate
17800Sstevel@tonic-gate#if defined(__amd64)
17810Sstevel@tonic-gate
17820Sstevel@tonic-gate	ENTRY(repoutsb)
17830Sstevel@tonic-gate	movl	%edx, %ecx
17840Sstevel@tonic-gate	movw	%di, %dx
17850Sstevel@tonic-gate	rep
17860Sstevel@tonic-gate	  outsb
17870Sstevel@tonic-gate	ret
17880Sstevel@tonic-gate	SET_SIZE(repoutsb)
17890Sstevel@tonic-gate
17900Sstevel@tonic-gate#elif defined(__i386)
17910Sstevel@tonic-gate
17920Sstevel@tonic-gate	ENTRY(repoutsb)
17930Sstevel@tonic-gate	pushl	%esi
17940Sstevel@tonic-gate	movl	IO_ADDR(%esp), %esi
17950Sstevel@tonic-gate	movl	IO_COUNT(%esp), %ecx
17960Sstevel@tonic-gate	movl	IO_PORT(%esp), %edx
17970Sstevel@tonic-gate	rep
17980Sstevel@tonic-gate	  outsb
17990Sstevel@tonic-gate	popl	%esi
18000Sstevel@tonic-gate	ret
18010Sstevel@tonic-gate	SET_SIZE(repoutsb)
18020Sstevel@tonic-gate
18030Sstevel@tonic-gate#endif	/* __i386 */
18040Sstevel@tonic-gate#endif	/* __lint */
18050Sstevel@tonic-gate
18060Sstevel@tonic-gate/*
18070Sstevel@tonic-gate * Output a stream of 32-bit words
18080Sstevel@tonic-gate * NOTE: count is a DWORD count
18090Sstevel@tonic-gate */
18100Sstevel@tonic-gate#if defined(__lint)
18110Sstevel@tonic-gate
18120Sstevel@tonic-gate/* ARGSUSED */
18130Sstevel@tonic-gatevoid
18140Sstevel@tonic-gaterepoutsd(int port, uint32_t *addr, int count)
18150Sstevel@tonic-gate{}
18160Sstevel@tonic-gate
18170Sstevel@tonic-gate#else	/* __lint */
18180Sstevel@tonic-gate
18190Sstevel@tonic-gate#if defined(__amd64)
18200Sstevel@tonic-gate
18210Sstevel@tonic-gate	ENTRY(repoutsd)
18220Sstevel@tonic-gate	movl	%edx, %ecx
18230Sstevel@tonic-gate	movw	%di, %dx
18240Sstevel@tonic-gate	rep
18250Sstevel@tonic-gate	  outsl
18260Sstevel@tonic-gate	ret
18270Sstevel@tonic-gate	SET_SIZE(repoutsd)
18280Sstevel@tonic-gate
18290Sstevel@tonic-gate#elif defined(__i386)
18300Sstevel@tonic-gate
18310Sstevel@tonic-gate	ENTRY(repoutsd)
18320Sstevel@tonic-gate	pushl	%esi
18330Sstevel@tonic-gate	movl	IO_ADDR(%esp), %esi
18340Sstevel@tonic-gate	movl	IO_COUNT(%esp), %ecx
18350Sstevel@tonic-gate	movl	IO_PORT(%esp), %edx
18360Sstevel@tonic-gate	rep
18370Sstevel@tonic-gate	  outsl
18380Sstevel@tonic-gate	popl	%esi
18390Sstevel@tonic-gate	ret
18400Sstevel@tonic-gate	SET_SIZE(repoutsd)
18410Sstevel@tonic-gate
18420Sstevel@tonic-gate#endif	/* __i386 */
18430Sstevel@tonic-gate#endif	/* __lint */
18440Sstevel@tonic-gate
18450Sstevel@tonic-gate/*
18461414Scindi * void int3(void)
18471414Scindi * void int18(void)
18480Sstevel@tonic-gate * void int20(void)
18497349SAdrian.Frost@Sun.COM * void int_cmci(void)
18500Sstevel@tonic-gate */
18510Sstevel@tonic-gate
18520Sstevel@tonic-gate#if defined(__lint)
18530Sstevel@tonic-gate
18540Sstevel@tonic-gatevoid
18551414Scindiint3(void)
18561414Scindi{}
18571414Scindi
18581414Scindivoid
18591414Scindiint18(void)
18601414Scindi{}
18611414Scindi
18621414Scindivoid
18630Sstevel@tonic-gateint20(void)
18640Sstevel@tonic-gate{}
18650Sstevel@tonic-gate
18667349SAdrian.Frost@Sun.COMvoid
18677349SAdrian.Frost@Sun.COMint_cmci(void)
18687349SAdrian.Frost@Sun.COM{}
18697349SAdrian.Frost@Sun.COM
18700Sstevel@tonic-gate#else	/* __lint */
18710Sstevel@tonic-gate
18721414Scindi	ENTRY(int3)
18731414Scindi	int	$T_BPTFLT
18741414Scindi	ret
18751414Scindi	SET_SIZE(int3)
18761414Scindi
18771414Scindi	ENTRY(int18)
18781414Scindi	int	$T_MCE
18791414Scindi	ret
18801414Scindi	SET_SIZE(int18)
18811414Scindi
18820Sstevel@tonic-gate	ENTRY(int20)
18830Sstevel@tonic-gate	movl	boothowto, %eax
18840Sstevel@tonic-gate	andl	$RB_DEBUG, %eax
18850Sstevel@tonic-gate	jz	1f
18860Sstevel@tonic-gate
18871414Scindi	int	$T_DBGENTR
18880Sstevel@tonic-gate1:
1889545Skalai	rep;	ret	/* use 2 byte return instruction when branch target */
1890545Skalai			/* AMD Software Optimization Guide - Section 6.2 */
18910Sstevel@tonic-gate	SET_SIZE(int20)
18920Sstevel@tonic-gate
18937349SAdrian.Frost@Sun.COM	ENTRY(int_cmci)
18947349SAdrian.Frost@Sun.COM	int	$T_ENOEXTFLT
18957349SAdrian.Frost@Sun.COM	ret
18967349SAdrian.Frost@Sun.COM	SET_SIZE(int_cmci)
18977349SAdrian.Frost@Sun.COM
18980Sstevel@tonic-gate#endif	/* __lint */
18990Sstevel@tonic-gate
19000Sstevel@tonic-gate#if defined(__lint)
19010Sstevel@tonic-gate
19020Sstevel@tonic-gate/* ARGSUSED */
19030Sstevel@tonic-gateint
19040Sstevel@tonic-gatescanc(size_t size, uchar_t *cp, uchar_t *table, uchar_t mask)
19050Sstevel@tonic-gate{ return (0); }
19060Sstevel@tonic-gate
19070Sstevel@tonic-gate#else	/* __lint */
19080Sstevel@tonic-gate
19090Sstevel@tonic-gate#if defined(__amd64)
19100Sstevel@tonic-gate
19110Sstevel@tonic-gate	ENTRY(scanc)
19120Sstevel@tonic-gate					/* rdi == size */
19130Sstevel@tonic-gate					/* rsi == cp */
19140Sstevel@tonic-gate					/* rdx == table */
19150Sstevel@tonic-gate					/* rcx == mask */
19160Sstevel@tonic-gate	addq	%rsi, %rdi		/* end = &cp[size] */
19177421SDaniel.Anderson@Sun.COM.scanloop:
19180Sstevel@tonic-gate	cmpq	%rdi, %rsi		/* while (cp < end */
19190Sstevel@tonic-gate	jnb	.scandone
19200Sstevel@tonic-gate	movzbq	(%rsi), %r8		/* %r8 = *cp */
19210Sstevel@tonic-gate	incq	%rsi			/* cp++ */
19220Sstevel@tonic-gate	testb	%cl, (%r8, %rdx)
19230Sstevel@tonic-gate	jz	.scanloop		/*  && (table[*cp] & mask) == 0) */
19240Sstevel@tonic-gate	decq	%rsi			/* (fix post-increment) */
19250Sstevel@tonic-gate.scandone:
19260Sstevel@tonic-gate	movl	%edi, %eax
19270Sstevel@tonic-gate	subl	%esi, %eax		/* return (end - cp) */
19280Sstevel@tonic-gate	ret
19290Sstevel@tonic-gate	SET_SIZE(scanc)
19300Sstevel@tonic-gate
19310Sstevel@tonic-gate#elif defined(__i386)
19327421SDaniel.Anderson@Sun.COM
19330Sstevel@tonic-gate	ENTRY(scanc)
19340Sstevel@tonic-gate	pushl	%edi
19350Sstevel@tonic-gate	pushl	%esi
19360Sstevel@tonic-gate	movb	24(%esp), %cl		/* mask = %cl */
19370Sstevel@tonic-gate	movl	16(%esp), %esi		/* cp = %esi */
19380Sstevel@tonic-gate	movl	20(%esp), %edx		/* table = %edx */
19390Sstevel@tonic-gate	movl	%esi, %edi
19400Sstevel@tonic-gate	addl	12(%esp), %edi		/* end = &cp[size]; */
19410Sstevel@tonic-gate.scanloop:
19420Sstevel@tonic-gate	cmpl	%edi, %esi		/* while (cp < end */
19430Sstevel@tonic-gate	jnb	.scandone
19440Sstevel@tonic-gate	movzbl	(%esi),  %eax		/* %al = *cp */
19450Sstevel@tonic-gate	incl	%esi			/* cp++ */
19460Sstevel@tonic-gate	movb	(%edx,  %eax), %al	/* %al = table[*cp] */
19470Sstevel@tonic-gate	testb	%al, %cl
19480Sstevel@tonic-gate	jz	.scanloop		/*   && (table[*cp] & mask) == 0) */
19490Sstevel@tonic-gate	dec	%esi			/* post-incremented */
19500Sstevel@tonic-gate.scandone:
19510Sstevel@tonic-gate	movl	%edi, %eax
19520Sstevel@tonic-gate	subl	%esi, %eax		/* return (end - cp) */
19530Sstevel@tonic-gate	popl	%esi
19540Sstevel@tonic-gate	popl	%edi
19550Sstevel@tonic-gate	ret
19560Sstevel@tonic-gate	SET_SIZE(scanc)
19570Sstevel@tonic-gate
19587421SDaniel.Anderson@Sun.COM#endif	/* __i386 */
19590Sstevel@tonic-gate#endif	/* __lint */
19600Sstevel@tonic-gate
19610Sstevel@tonic-gate/*
19620Sstevel@tonic-gate * Replacement functions for ones that are normally inlined.
19630Sstevel@tonic-gate * In addition to the copy in i86.il, they are defined here just in case.
19640Sstevel@tonic-gate */
19650Sstevel@tonic-gate
19660Sstevel@tonic-gate#if defined(__lint)
19670Sstevel@tonic-gate
19683446Smrjulong_t
19690Sstevel@tonic-gateintr_clear(void)
19703446Smrj{ return (0); }
19713446Smrj
19723446Smrjulong_t
19730Sstevel@tonic-gateclear_int_flag(void)
19743446Smrj{ return (0); }
19750Sstevel@tonic-gate
19760Sstevel@tonic-gate#else	/* __lint */
19770Sstevel@tonic-gate
19780Sstevel@tonic-gate#if defined(__amd64)
19790Sstevel@tonic-gate
19800Sstevel@tonic-gate	ENTRY(intr_clear)
19810Sstevel@tonic-gate	ENTRY(clear_int_flag)
19820Sstevel@tonic-gate	pushfq
19830Sstevel@tonic-gate	popq	%rax
19845084Sjohnlev#if defined(__xpv)
19855084Sjohnlev	leaq	xpv_panicking, %rdi
19865084Sjohnlev	movl	(%rdi), %edi
19875084Sjohnlev	cmpl	$0, %edi
19885084Sjohnlev	jne	2f
19895084Sjohnlev	CLIRET(%rdi, %dl)	/* returns event mask in %dl */
19905084Sjohnlev	/*
19915084Sjohnlev	 * Synthesize the PS_IE bit from the event mask bit
19925084Sjohnlev	 */
19935084Sjohnlev	andq    $_BITNOT(PS_IE), %rax
19945084Sjohnlev	testb	$1, %dl
19955084Sjohnlev	jnz	1f
19965084Sjohnlev	orq	$PS_IE, %rax
19975084Sjohnlev1:
19985084Sjohnlev	ret
19995084Sjohnlev2:
20005084Sjohnlev#endif
20013446Smrj	CLI(%rdi)
20020Sstevel@tonic-gate	ret
20030Sstevel@tonic-gate	SET_SIZE(clear_int_flag)
20040Sstevel@tonic-gate	SET_SIZE(intr_clear)
20050Sstevel@tonic-gate
20060Sstevel@tonic-gate#elif defined(__i386)
20070Sstevel@tonic-gate
20080Sstevel@tonic-gate	ENTRY(intr_clear)
20090Sstevel@tonic-gate	ENTRY(clear_int_flag)
20100Sstevel@tonic-gate	pushfl
20110Sstevel@tonic-gate	popl	%eax
20125084Sjohnlev#if defined(__xpv)
20135084Sjohnlev	leal	xpv_panicking, %edx
20145084Sjohnlev	movl	(%edx), %edx
20155084Sjohnlev	cmpl	$0, %edx
20165084Sjohnlev	jne	2f
20175084Sjohnlev	CLIRET(%edx, %cl)	/* returns event mask in %cl */
20185084Sjohnlev	/*
20195084Sjohnlev	 * Synthesize the PS_IE bit from the event mask bit
20205084Sjohnlev	 */
20215084Sjohnlev	andl    $_BITNOT(PS_IE), %eax
20225084Sjohnlev	testb	$1, %cl
20235084Sjohnlev	jnz	1f
20245084Sjohnlev	orl	$PS_IE, %eax
20255084Sjohnlev1:
20265084Sjohnlev	ret
20275084Sjohnlev2:
20285084Sjohnlev#endif
20293446Smrj	CLI(%edx)
20300Sstevel@tonic-gate	ret
20310Sstevel@tonic-gate	SET_SIZE(clear_int_flag)
20320Sstevel@tonic-gate	SET_SIZE(intr_clear)
20330Sstevel@tonic-gate
20340Sstevel@tonic-gate#endif	/* __i386 */
20350Sstevel@tonic-gate#endif	/* __lint */
20360Sstevel@tonic-gate
20370Sstevel@tonic-gate#if defined(__lint)
20380Sstevel@tonic-gate
20390Sstevel@tonic-gatestruct cpu *
20400Sstevel@tonic-gatecurcpup(void)
20410Sstevel@tonic-gate{ return 0; }
20420Sstevel@tonic-gate
20430Sstevel@tonic-gate#else	/* __lint */
20440Sstevel@tonic-gate
20450Sstevel@tonic-gate#if defined(__amd64)
20460Sstevel@tonic-gate
20470Sstevel@tonic-gate	ENTRY(curcpup)
20480Sstevel@tonic-gate	movq	%gs:CPU_SELF, %rax
20490Sstevel@tonic-gate	ret
20500Sstevel@tonic-gate	SET_SIZE(curcpup)
20510Sstevel@tonic-gate
20520Sstevel@tonic-gate#elif defined(__i386)
20530Sstevel@tonic-gate
20540Sstevel@tonic-gate	ENTRY(curcpup)
20550Sstevel@tonic-gate	movl	%gs:CPU_SELF, %eax
20560Sstevel@tonic-gate	ret
20570Sstevel@tonic-gate	SET_SIZE(curcpup)
20580Sstevel@tonic-gate
20590Sstevel@tonic-gate#endif	/* __i386 */
20600Sstevel@tonic-gate#endif	/* __lint */
20610Sstevel@tonic-gate
20627421SDaniel.Anderson@Sun.COM/* htonll(), ntohll(), htonl(), ntohl(), htons(), ntohs()
20637421SDaniel.Anderson@Sun.COM * These functions reverse the byte order of the input parameter and returns
20647421SDaniel.Anderson@Sun.COM * the result.  This is to convert the byte order from host byte order
20657421SDaniel.Anderson@Sun.COM * (little endian) to network byte order (big endian), or vice versa.
20667421SDaniel.Anderson@Sun.COM */
20677421SDaniel.Anderson@Sun.COM
20680Sstevel@tonic-gate#if defined(__lint)
20690Sstevel@tonic-gate
20707421SDaniel.Anderson@Sun.COMuint64_t
20717421SDaniel.Anderson@Sun.COMhtonll(uint64_t i)
20727421SDaniel.Anderson@Sun.COM{ return (i); }
20737421SDaniel.Anderson@Sun.COM
20747421SDaniel.Anderson@Sun.COMuint64_t
20757421SDaniel.Anderson@Sun.COMntohll(uint64_t i)
20767421SDaniel.Anderson@Sun.COM{ return (i); }
20777421SDaniel.Anderson@Sun.COM
20780Sstevel@tonic-gateuint32_t
20790Sstevel@tonic-gatehtonl(uint32_t i)
20807421SDaniel.Anderson@Sun.COM{ return (i); }
20817421SDaniel.Anderson@Sun.COM
20820Sstevel@tonic-gateuint32_t
20830Sstevel@tonic-gatentohl(uint32_t i)
20847421SDaniel.Anderson@Sun.COM{ return (i); }
20857421SDaniel.Anderson@Sun.COM
20867421SDaniel.Anderson@Sun.COMuint16_t
20877421SDaniel.Anderson@Sun.COMhtons(uint16_t i)
20887421SDaniel.Anderson@Sun.COM{ return (i); }
20897421SDaniel.Anderson@Sun.COM
20907421SDaniel.Anderson@Sun.COMuint16_t
20917421SDaniel.Anderson@Sun.COMntohs(uint16_t i)
20927421SDaniel.Anderson@Sun.COM{ return (i); }
20930Sstevel@tonic-gate
20940Sstevel@tonic-gate#else	/* __lint */
20950Sstevel@tonic-gate
20960Sstevel@tonic-gate#if defined(__amd64)
20970Sstevel@tonic-gate
20987421SDaniel.Anderson@Sun.COM	ENTRY(htonll)
20997421SDaniel.Anderson@Sun.COM	ALTENTRY(ntohll)
21007421SDaniel.Anderson@Sun.COM	movq	%rdi, %rax
21017421SDaniel.Anderson@Sun.COM	bswapq	%rax
21027421SDaniel.Anderson@Sun.COM	ret
21037421SDaniel.Anderson@Sun.COM	SET_SIZE(ntohll)
21047421SDaniel.Anderson@Sun.COM	SET_SIZE(htonll)
21057421SDaniel.Anderson@Sun.COM
21060Sstevel@tonic-gate	/* XX64 there must be shorter sequences for this */
21070Sstevel@tonic-gate	ENTRY(htonl)
21080Sstevel@tonic-gate	ALTENTRY(ntohl)
21090Sstevel@tonic-gate	movl	%edi, %eax
21100Sstevel@tonic-gate	bswap	%eax
21110Sstevel@tonic-gate	ret
21120Sstevel@tonic-gate	SET_SIZE(ntohl)
21130Sstevel@tonic-gate	SET_SIZE(htonl)
21140Sstevel@tonic-gate
21157421SDaniel.Anderson@Sun.COM	/* XX64 there must be better sequences for this */
21167421SDaniel.Anderson@Sun.COM	ENTRY(htons)
21177421SDaniel.Anderson@Sun.COM	ALTENTRY(ntohs)
21187421SDaniel.Anderson@Sun.COM	movl	%edi, %eax
21197421SDaniel.Anderson@Sun.COM	bswap	%eax
21207421SDaniel.Anderson@Sun.COM	shrl	$16, %eax
21217421SDaniel.Anderson@Sun.COM	ret
21227421SDaniel.Anderson@Sun.COM	SET_SIZE(ntohs)
21237421SDaniel.Anderson@Sun.COM	SET_SIZE(htons)
21247421SDaniel.Anderson@Sun.COM
21250Sstevel@tonic-gate#elif defined(__i386)
21260Sstevel@tonic-gate
21277421SDaniel.Anderson@Sun.COM	ENTRY(htonll)
21287421SDaniel.Anderson@Sun.COM	ALTENTRY(ntohll)
21297421SDaniel.Anderson@Sun.COM	movl	4(%esp), %edx
21307421SDaniel.Anderson@Sun.COM	movl	8(%esp), %eax
21317421SDaniel.Anderson@Sun.COM	bswap	%edx
21327421SDaniel.Anderson@Sun.COM	bswap	%eax
21337421SDaniel.Anderson@Sun.COM	ret
21347421SDaniel.Anderson@Sun.COM	SET_SIZE(ntohll)
21357421SDaniel.Anderson@Sun.COM	SET_SIZE(htonll)
21367421SDaniel.Anderson@Sun.COM
21370Sstevel@tonic-gate	ENTRY(htonl)
21380Sstevel@tonic-gate	ALTENTRY(ntohl)
21390Sstevel@tonic-gate	movl	4(%esp), %eax
21400Sstevel@tonic-gate	bswap	%eax
21410Sstevel@tonic-gate	ret
21420Sstevel@tonic-gate	SET_SIZE(ntohl)
21430Sstevel@tonic-gate	SET_SIZE(htonl)
21440Sstevel@tonic-gate
21450Sstevel@tonic-gate	ENTRY(htons)
21460Sstevel@tonic-gate	ALTENTRY(ntohs)
21470Sstevel@tonic-gate	movl	4(%esp), %eax
21480Sstevel@tonic-gate	bswap	%eax
21490Sstevel@tonic-gate	shrl	$16, %eax
21500Sstevel@tonic-gate	ret
21510Sstevel@tonic-gate	SET_SIZE(ntohs)
21520Sstevel@tonic-gate	SET_SIZE(htons)
21530Sstevel@tonic-gate
21540Sstevel@tonic-gate#endif	/* __i386 */
21550Sstevel@tonic-gate#endif	/* __lint */
21560Sstevel@tonic-gate
21570Sstevel@tonic-gate
21580Sstevel@tonic-gate#if defined(__lint)
21590Sstevel@tonic-gate
21600Sstevel@tonic-gate/* ARGSUSED */
21610Sstevel@tonic-gatevoid
21623446Smrjintr_restore(ulong_t i)
21630Sstevel@tonic-gate{ return; }
21640Sstevel@tonic-gate
21650Sstevel@tonic-gate/* ARGSUSED */
21660Sstevel@tonic-gatevoid
21673446Smrjrestore_int_flag(ulong_t i)
21680Sstevel@tonic-gate{ return; }
21690Sstevel@tonic-gate
21700Sstevel@tonic-gate#else	/* __lint */
21710Sstevel@tonic-gate
21720Sstevel@tonic-gate#if defined(__amd64)
21730Sstevel@tonic-gate
21740Sstevel@tonic-gate	ENTRY(intr_restore)
21750Sstevel@tonic-gate	ENTRY(restore_int_flag)
21766336Sbholler	testq	$PS_IE, %rdi
21776336Sbholler	jz	1f
21785084Sjohnlev#if defined(__xpv)
21795084Sjohnlev	leaq	xpv_panicking, %rsi
21805084Sjohnlev	movl	(%rsi), %esi
21815084Sjohnlev	cmpl	$0, %esi
21825084Sjohnlev	jne	1f
21835084Sjohnlev	/*
21845084Sjohnlev	 * Since we're -really- running unprivileged, our attempt
21855084Sjohnlev	 * to change the state of the IF bit will be ignored.
21865084Sjohnlev	 * The virtual IF bit is tweaked by CLI and STI.
21875084Sjohnlev	 */
21885084Sjohnlev	IE_TO_EVENT_MASK(%rsi, %rdi)
21896336Sbholler#else
21906336Sbholler	sti
21916336Sbholler#endif
21925084Sjohnlev1:
21930Sstevel@tonic-gate	ret
21940Sstevel@tonic-gate	SET_SIZE(restore_int_flag)
21950Sstevel@tonic-gate	SET_SIZE(intr_restore)
21960Sstevel@tonic-gate
21970Sstevel@tonic-gate#elif defined(__i386)
21980Sstevel@tonic-gate
21990Sstevel@tonic-gate	ENTRY(intr_restore)
22000Sstevel@tonic-gate	ENTRY(restore_int_flag)
22016336Sbholler	testl	$PS_IE, 4(%esp)
22026336Sbholler	jz	1f
22035084Sjohnlev#if defined(__xpv)
22045084Sjohnlev	leal	xpv_panicking, %edx
22055084Sjohnlev	movl	(%edx), %edx
22065084Sjohnlev	cmpl	$0, %edx
22075084Sjohnlev	jne	1f
22085084Sjohnlev	/*
22095084Sjohnlev	 * Since we're -really- running unprivileged, our attempt
22105084Sjohnlev	 * to change the state of the IF bit will be ignored.
22115084Sjohnlev	 * The virtual IF bit is tweaked by CLI and STI.
22125084Sjohnlev	 */
22136356Smrj	IE_TO_EVENT_MASK(%edx, 4(%esp))
22146336Sbholler#else
22156336Sbholler	sti
22166336Sbholler#endif
22175084Sjohnlev1:
22180Sstevel@tonic-gate	ret
22190Sstevel@tonic-gate	SET_SIZE(restore_int_flag)
22200Sstevel@tonic-gate	SET_SIZE(intr_restore)
22210Sstevel@tonic-gate
22220Sstevel@tonic-gate#endif	/* __i386 */
22230Sstevel@tonic-gate#endif	/* __lint */
22240Sstevel@tonic-gate
22250Sstevel@tonic-gate#if defined(__lint)
22260Sstevel@tonic-gate
22270Sstevel@tonic-gatevoid
22280Sstevel@tonic-gatesti(void)
22290Sstevel@tonic-gate{}
22300Sstevel@tonic-gate
22313446Smrjvoid
22323446Smrjcli(void)
22333446Smrj{}
22343446Smrj
22350Sstevel@tonic-gate#else	/* __lint */
22360Sstevel@tonic-gate
22370Sstevel@tonic-gate	ENTRY(sti)
22383446Smrj	STI
22390Sstevel@tonic-gate	ret
22400Sstevel@tonic-gate	SET_SIZE(sti)
22410Sstevel@tonic-gate
22423446Smrj	ENTRY(cli)
22433446Smrj#if defined(__amd64)
22443446Smrj	CLI(%rax)
22453446Smrj#elif defined(__i386)
22463446Smrj	CLI(%eax)
22473446Smrj#endif	/* __i386 */
22483446Smrj	ret
22493446Smrj	SET_SIZE(cli)
22503446Smrj
22510Sstevel@tonic-gate#endif	/* __lint */
22520Sstevel@tonic-gate
22530Sstevel@tonic-gate#if defined(__lint)
22540Sstevel@tonic-gate
22550Sstevel@tonic-gatedtrace_icookie_t
22560Sstevel@tonic-gatedtrace_interrupt_disable(void)
22570Sstevel@tonic-gate{ return (0); }
22580Sstevel@tonic-gate
22590Sstevel@tonic-gate#else   /* __lint */
22600Sstevel@tonic-gate
22610Sstevel@tonic-gate#if defined(__amd64)
22620Sstevel@tonic-gate
22630Sstevel@tonic-gate	ENTRY(dtrace_interrupt_disable)
22640Sstevel@tonic-gate	pushfq
22650Sstevel@tonic-gate	popq	%rax
22665084Sjohnlev#if defined(__xpv)
22675084Sjohnlev	leaq	xpv_panicking, %rdi
22685084Sjohnlev	movl	(%rdi), %edi
22695084Sjohnlev	cmpl	$0, %edi
22707532SSean.Ye@Sun.COM	jne	.dtrace_interrupt_disable_done
22715084Sjohnlev	CLIRET(%rdi, %dl)	/* returns event mask in %dl */
22725084Sjohnlev	/*
22735084Sjohnlev	 * Synthesize the PS_IE bit from the event mask bit
22745084Sjohnlev	 */
22755084Sjohnlev	andq    $_BITNOT(PS_IE), %rax
22765084Sjohnlev	testb	$1, %dl
22777532SSean.Ye@Sun.COM	jnz	.dtrace_interrupt_disable_done
22785084Sjohnlev	orq	$PS_IE, %rax
22795084Sjohnlev#else
22803446Smrj	CLI(%rdx)
22815084Sjohnlev#endif
22827532SSean.Ye@Sun.COM.dtrace_interrupt_disable_done:
22830Sstevel@tonic-gate	ret
22840Sstevel@tonic-gate	SET_SIZE(dtrace_interrupt_disable)
22850Sstevel@tonic-gate
22860Sstevel@tonic-gate#elif defined(__i386)
22870Sstevel@tonic-gate
22880Sstevel@tonic-gate	ENTRY(dtrace_interrupt_disable)
22890Sstevel@tonic-gate	pushfl
22900Sstevel@tonic-gate	popl	%eax
22915084Sjohnlev#if defined(__xpv)
22925084Sjohnlev	leal	xpv_panicking, %edx
22935084Sjohnlev	movl	(%edx), %edx
22945084Sjohnlev	cmpl	$0, %edx
22957532SSean.Ye@Sun.COM	jne	.dtrace_interrupt_disable_done
22965084Sjohnlev	CLIRET(%edx, %cl)	/* returns event mask in %cl */
22975084Sjohnlev	/*
22985084Sjohnlev	 * Synthesize the PS_IE bit from the event mask bit
22995084Sjohnlev	 */
23005084Sjohnlev	andl    $_BITNOT(PS_IE), %eax
23015084Sjohnlev	testb	$1, %cl
23027532SSean.Ye@Sun.COM	jnz	.dtrace_interrupt_disable_done
23035084Sjohnlev	orl	$PS_IE, %eax
23045084Sjohnlev#else
23053446Smrj	CLI(%edx)
23065084Sjohnlev#endif
23077532SSean.Ye@Sun.COM.dtrace_interrupt_disable_done:
23080Sstevel@tonic-gate	ret
23090Sstevel@tonic-gate	SET_SIZE(dtrace_interrupt_disable)
23100Sstevel@tonic-gate
23110Sstevel@tonic-gate#endif	/* __i386 */
23120Sstevel@tonic-gate#endif	/* __lint */
23130Sstevel@tonic-gate
23140Sstevel@tonic-gate#if defined(__lint)
23150Sstevel@tonic-gate
23160Sstevel@tonic-gate/*ARGSUSED*/
23170Sstevel@tonic-gatevoid
23180Sstevel@tonic-gatedtrace_interrupt_enable(dtrace_icookie_t cookie)
23190Sstevel@tonic-gate{}
23200Sstevel@tonic-gate
23210Sstevel@tonic-gate#else	/* __lint */
23220Sstevel@tonic-gate
23230Sstevel@tonic-gate#if defined(__amd64)
23240Sstevel@tonic-gate
23250Sstevel@tonic-gate	ENTRY(dtrace_interrupt_enable)
23260Sstevel@tonic-gate	pushq	%rdi
23270Sstevel@tonic-gate	popfq
23285084Sjohnlev#if defined(__xpv)
23295084Sjohnlev	leaq	xpv_panicking, %rdx
23305084Sjohnlev	movl	(%rdx), %edx
23315084Sjohnlev	cmpl	$0, %edx
23327532SSean.Ye@Sun.COM	jne	.dtrace_interrupt_enable_done
23335084Sjohnlev	/*
23345084Sjohnlev	 * Since we're -really- running unprivileged, our attempt
23355084Sjohnlev	 * to change the state of the IF bit will be ignored. The
23365084Sjohnlev	 * virtual IF bit is tweaked by CLI and STI.
23375084Sjohnlev	 */
23385084Sjohnlev	IE_TO_EVENT_MASK(%rdx, %rdi)
23395084Sjohnlev#endif
23407532SSean.Ye@Sun.COM.dtrace_interrupt_enable_done:
23410Sstevel@tonic-gate	ret
23420Sstevel@tonic-gate	SET_SIZE(dtrace_interrupt_enable)
23430Sstevel@tonic-gate
23440Sstevel@tonic-gate#elif defined(__i386)
23450Sstevel@tonic-gate
23460Sstevel@tonic-gate	ENTRY(dtrace_interrupt_enable)
23470Sstevel@tonic-gate	movl	4(%esp), %eax
23480Sstevel@tonic-gate	pushl	%eax
23490Sstevel@tonic-gate	popfl
23505084Sjohnlev#if defined(__xpv)
23515084Sjohnlev	leal	xpv_panicking, %edx
23525084Sjohnlev	movl	(%edx), %edx
23535084Sjohnlev	cmpl	$0, %edx
23547532SSean.Ye@Sun.COM	jne	.dtrace_interrupt_enable_done
23555084Sjohnlev	/*
23565084Sjohnlev	 * Since we're -really- running unprivileged, our attempt
23575084Sjohnlev	 * to change the state of the IF bit will be ignored. The
23585084Sjohnlev	 * virtual IF bit is tweaked by CLI and STI.
23595084Sjohnlev	 */
23605084Sjohnlev	IE_TO_EVENT_MASK(%edx, %eax)
23615084Sjohnlev#endif
23627532SSean.Ye@Sun.COM.dtrace_interrupt_enable_done:
23630Sstevel@tonic-gate	ret
23640Sstevel@tonic-gate	SET_SIZE(dtrace_interrupt_enable)
23650Sstevel@tonic-gate
23660Sstevel@tonic-gate#endif	/* __i386 */
23670Sstevel@tonic-gate#endif	/* __lint */
23680Sstevel@tonic-gate
23690Sstevel@tonic-gate
23700Sstevel@tonic-gate#if defined(lint)
23710Sstevel@tonic-gate
23720Sstevel@tonic-gatevoid
23730Sstevel@tonic-gatedtrace_membar_producer(void)
23740Sstevel@tonic-gate{}
23750Sstevel@tonic-gate
23760Sstevel@tonic-gatevoid
23770Sstevel@tonic-gatedtrace_membar_consumer(void)
23780Sstevel@tonic-gate{}
23790Sstevel@tonic-gate
23800Sstevel@tonic-gate#else	/* __lint */
23810Sstevel@tonic-gate
23820Sstevel@tonic-gate	ENTRY(dtrace_membar_producer)
2383545Skalai	rep;	ret	/* use 2 byte return instruction when branch target */
2384545Skalai			/* AMD Software Optimization Guide - Section 6.2 */
23850Sstevel@tonic-gate	SET_SIZE(dtrace_membar_producer)
23860Sstevel@tonic-gate
23870Sstevel@tonic-gate	ENTRY(dtrace_membar_consumer)
2388545Skalai	rep;	ret	/* use 2 byte return instruction when branch target */
2389545Skalai			/* AMD Software Optimization Guide - Section 6.2 */
23900Sstevel@tonic-gate	SET_SIZE(dtrace_membar_consumer)
23910Sstevel@tonic-gate
23920Sstevel@tonic-gate#endif	/* __lint */
23930Sstevel@tonic-gate
23940Sstevel@tonic-gate#if defined(__lint)
23950Sstevel@tonic-gate
23960Sstevel@tonic-gatekthread_id_t
23970Sstevel@tonic-gatethreadp(void)
23980Sstevel@tonic-gate{ return ((kthread_id_t)0); }
23990Sstevel@tonic-gate
24000Sstevel@tonic-gate#else	/* __lint */
24010Sstevel@tonic-gate
24020Sstevel@tonic-gate#if defined(__amd64)
24030Sstevel@tonic-gate
24040Sstevel@tonic-gate	ENTRY(threadp)
24050Sstevel@tonic-gate	movq	%gs:CPU_THREAD, %rax
24060Sstevel@tonic-gate	ret
24070Sstevel@tonic-gate	SET_SIZE(threadp)
24080Sstevel@tonic-gate
24090Sstevel@tonic-gate#elif defined(__i386)
24100Sstevel@tonic-gate
24110Sstevel@tonic-gate	ENTRY(threadp)
24120Sstevel@tonic-gate	movl	%gs:CPU_THREAD, %eax
24130Sstevel@tonic-gate	ret
24140Sstevel@tonic-gate	SET_SIZE(threadp)
24150Sstevel@tonic-gate
24160Sstevel@tonic-gate#endif	/* __i386 */
24170Sstevel@tonic-gate#endif	/* __lint */
24180Sstevel@tonic-gate
24190Sstevel@tonic-gate/*
24200Sstevel@tonic-gate *   Checksum routine for Internet Protocol Headers
24210Sstevel@tonic-gate */
24220Sstevel@tonic-gate
24230Sstevel@tonic-gate#if defined(__lint)
24240Sstevel@tonic-gate
24250Sstevel@tonic-gate/* ARGSUSED */
24260Sstevel@tonic-gateunsigned int
24270Sstevel@tonic-gateip_ocsum(
24280Sstevel@tonic-gate	ushort_t *address,	/* ptr to 1st message buffer */
24290Sstevel@tonic-gate	int halfword_count,	/* length of data */
24300Sstevel@tonic-gate	unsigned int sum)	/* partial checksum */
24310Sstevel@tonic-gate{
24320Sstevel@tonic-gate	int		i;
24330Sstevel@tonic-gate	unsigned int	psum = 0;	/* partial sum */
24340Sstevel@tonic-gate
24350Sstevel@tonic-gate	for (i = 0; i < halfword_count; i++, address++) {
24360Sstevel@tonic-gate		psum += *address;
24370Sstevel@tonic-gate	}
24380Sstevel@tonic-gate
24390Sstevel@tonic-gate	while ((psum >> 16) != 0) {
24400Sstevel@tonic-gate		psum = (psum & 0xffff) + (psum >> 16);
24410Sstevel@tonic-gate	}
24420Sstevel@tonic-gate
24430Sstevel@tonic-gate	psum += sum;
24440Sstevel@tonic-gate
24450Sstevel@tonic-gate	while ((psum >> 16) != 0) {
24460Sstevel@tonic-gate		psum = (psum & 0xffff) + (psum >> 16);
24470Sstevel@tonic-gate	}
24480Sstevel@tonic-gate
24490Sstevel@tonic-gate	return (psum);
24500Sstevel@tonic-gate}
24510Sstevel@tonic-gate
24520Sstevel@tonic-gate#else	/* __lint */
24530Sstevel@tonic-gate
24540Sstevel@tonic-gate#if defined(__amd64)
24550Sstevel@tonic-gate
24560Sstevel@tonic-gate	ENTRY(ip_ocsum)
24570Sstevel@tonic-gate	pushq	%rbp
24580Sstevel@tonic-gate	movq	%rsp, %rbp
24590Sstevel@tonic-gate#ifdef DEBUG
24603446Smrj	movq	postbootkernelbase(%rip), %rax
24610Sstevel@tonic-gate	cmpq	%rax, %rdi
24620Sstevel@tonic-gate	jnb	1f
24630Sstevel@tonic-gate	xorl	%eax, %eax
24640Sstevel@tonic-gate	movq	%rdi, %rsi
24650Sstevel@tonic-gate	leaq	.ip_ocsum_panic_msg(%rip), %rdi
24660Sstevel@tonic-gate	call	panic
24670Sstevel@tonic-gate	/*NOTREACHED*/
24680Sstevel@tonic-gate.ip_ocsum_panic_msg:
24690Sstevel@tonic-gate	.string	"ip_ocsum: address 0x%p below kernelbase\n"
24700Sstevel@tonic-gate1:
24710Sstevel@tonic-gate#endif
24720Sstevel@tonic-gate	movl	%esi, %ecx	/* halfword_count */
24730Sstevel@tonic-gate	movq	%rdi, %rsi	/* address */
24740Sstevel@tonic-gate				/* partial sum in %edx */
24750Sstevel@tonic-gate	xorl	%eax, %eax
24760Sstevel@tonic-gate	testl	%ecx, %ecx
24770Sstevel@tonic-gate	jz	.ip_ocsum_done
24780Sstevel@tonic-gate	testq	$3, %rsi
24790Sstevel@tonic-gate	jnz	.ip_csum_notaligned
24800Sstevel@tonic-gate.ip_csum_aligned:	/* XX64 opportunities for 8-byte operations? */
24810Sstevel@tonic-gate.next_iter:
24820Sstevel@tonic-gate	/* XX64 opportunities for prefetch? */
24830Sstevel@tonic-gate	/* XX64 compute csum with 64 bit quantities? */
24840Sstevel@tonic-gate	subl	$32, %ecx
24850Sstevel@tonic-gate	jl	.less_than_32
24860Sstevel@tonic-gate
24870Sstevel@tonic-gate	addl	0(%rsi), %edx
24880Sstevel@tonic-gate.only60:
24890Sstevel@tonic-gate	adcl	4(%rsi), %eax
24900Sstevel@tonic-gate.only56:
24910Sstevel@tonic-gate	adcl	8(%rsi), %edx
24920Sstevel@tonic-gate.only52:
24930Sstevel@tonic-gate	adcl	12(%rsi), %eax
24940Sstevel@tonic-gate.only48:
24950Sstevel@tonic-gate	adcl	16(%rsi), %edx
24960Sstevel@tonic-gate.only44:
24970Sstevel@tonic-gate	adcl	20(%rsi), %eax
24980Sstevel@tonic-gate.only40:
24990Sstevel@tonic-gate	adcl	24(%rsi), %edx
25000Sstevel@tonic-gate.only36:
25010Sstevel@tonic-gate	adcl	28(%rsi), %eax
25020Sstevel@tonic-gate.only32:
25030Sstevel@tonic-gate	adcl	32(%rsi), %edx
25040Sstevel@tonic-gate.only28:
25050Sstevel@tonic-gate	adcl	36(%rsi), %eax
25060Sstevel@tonic-gate.only24:
25070Sstevel@tonic-gate	adcl	40(%rsi), %edx
25080Sstevel@tonic-gate.only20:
25090Sstevel@tonic-gate	adcl	44(%rsi), %eax
25100Sstevel@tonic-gate.only16:
25110Sstevel@tonic-gate	adcl	48(%rsi), %edx
25120Sstevel@tonic-gate.only12:
25130Sstevel@tonic-gate	adcl	52(%rsi), %eax
25140Sstevel@tonic-gate.only8:
25150Sstevel@tonic-gate	adcl	56(%rsi), %edx
25160Sstevel@tonic-gate.only4:
25170Sstevel@tonic-gate	adcl	60(%rsi), %eax	/* could be adding -1 and -1 with a carry */
25180Sstevel@tonic-gate.only0:
25190Sstevel@tonic-gate	adcl	$0, %eax	/* could be adding -1 in eax with a carry */
25200Sstevel@tonic-gate	adcl	$0, %eax
25210Sstevel@tonic-gate
25220Sstevel@tonic-gate	addq	$64, %rsi
25230Sstevel@tonic-gate	testl	%ecx, %ecx
25240Sstevel@tonic-gate	jnz	.next_iter
25250Sstevel@tonic-gate
25260Sstevel@tonic-gate.ip_ocsum_done:
25270Sstevel@tonic-gate	addl	%eax, %edx
25280Sstevel@tonic-gate	adcl	$0, %edx
25290Sstevel@tonic-gate	movl	%edx, %eax	/* form a 16 bit checksum by */
25300Sstevel@tonic-gate	shrl	$16, %eax	/* adding two halves of 32 bit checksum */
25310Sstevel@tonic-gate	addw	%dx, %ax
25320Sstevel@tonic-gate	adcw	$0, %ax
25330Sstevel@tonic-gate	andl	$0xffff, %eax
25340Sstevel@tonic-gate	leave
25350Sstevel@tonic-gate	ret
25360Sstevel@tonic-gate
25370Sstevel@tonic-gate.ip_csum_notaligned:
25380Sstevel@tonic-gate	xorl	%edi, %edi
25390Sstevel@tonic-gate	movw	(%rsi), %di
25400Sstevel@tonic-gate	addl	%edi, %edx
25410Sstevel@tonic-gate	adcl	$0, %edx
25420Sstevel@tonic-gate	addq	$2, %rsi
25430Sstevel@tonic-gate	decl	%ecx
25440Sstevel@tonic-gate	jmp	.ip_csum_aligned
25450Sstevel@tonic-gate
25460Sstevel@tonic-gate.less_than_32:
25470Sstevel@tonic-gate	addl	$32, %ecx
25480Sstevel@tonic-gate	testl	$1, %ecx
25490Sstevel@tonic-gate	jz	.size_aligned
25500Sstevel@tonic-gate	andl	$0xfe, %ecx
25510Sstevel@tonic-gate	movzwl	(%rsi, %rcx, 2), %edi
25520Sstevel@tonic-gate	addl	%edi, %edx
25530Sstevel@tonic-gate	adcl	$0, %edx
25540Sstevel@tonic-gate.size_aligned:
25550Sstevel@tonic-gate	movl	%ecx, %edi
25560Sstevel@tonic-gate	shrl	$1, %ecx
25570Sstevel@tonic-gate	shl	$1, %edi
25580Sstevel@tonic-gate	subq	$64, %rdi
25590Sstevel@tonic-gate	addq	%rdi, %rsi
25600Sstevel@tonic-gate	leaq    .ip_ocsum_jmptbl(%rip), %rdi
25610Sstevel@tonic-gate	leaq	(%rdi, %rcx, 8), %rdi
25620Sstevel@tonic-gate	xorl	%ecx, %ecx
25630Sstevel@tonic-gate	clc
25640Sstevel@tonic-gate	jmp 	*(%rdi)
25650Sstevel@tonic-gate
25660Sstevel@tonic-gate	.align	8
25670Sstevel@tonic-gate.ip_ocsum_jmptbl:
25680Sstevel@tonic-gate	.quad	.only0, .only4, .only8, .only12, .only16, .only20
25690Sstevel@tonic-gate	.quad	.only24, .only28, .only32, .only36, .only40, .only44
25700Sstevel@tonic-gate	.quad	.only48, .only52, .only56, .only60
25710Sstevel@tonic-gate	SET_SIZE(ip_ocsum)
25720Sstevel@tonic-gate
25730Sstevel@tonic-gate#elif defined(__i386)
25740Sstevel@tonic-gate
25750Sstevel@tonic-gate	ENTRY(ip_ocsum)
25760Sstevel@tonic-gate	pushl	%ebp
25770Sstevel@tonic-gate	movl	%esp, %ebp
25780Sstevel@tonic-gate	pushl	%ebx
25790Sstevel@tonic-gate	pushl	%esi
25800Sstevel@tonic-gate	pushl	%edi
25810Sstevel@tonic-gate	movl	12(%ebp), %ecx	/* count of half words */
25820Sstevel@tonic-gate	movl	16(%ebp), %edx	/* partial checksum */
25830Sstevel@tonic-gate	movl	8(%ebp), %esi
25840Sstevel@tonic-gate	xorl	%eax, %eax
25850Sstevel@tonic-gate	testl	%ecx, %ecx
25860Sstevel@tonic-gate	jz	.ip_ocsum_done
25870Sstevel@tonic-gate
25880Sstevel@tonic-gate	testl	$3, %esi
25890Sstevel@tonic-gate	jnz	.ip_csum_notaligned
25900Sstevel@tonic-gate.ip_csum_aligned:
25910Sstevel@tonic-gate.next_iter:
25920Sstevel@tonic-gate	subl	$32, %ecx
25930Sstevel@tonic-gate	jl	.less_than_32
25940Sstevel@tonic-gate
25950Sstevel@tonic-gate	addl	0(%esi), %edx
25960Sstevel@tonic-gate.only60:
25970Sstevel@tonic-gate	adcl	4(%esi), %eax
25980Sstevel@tonic-gate.only56:
25990Sstevel@tonic-gate	adcl	8(%esi), %edx
26000Sstevel@tonic-gate.only52:
26010Sstevel@tonic-gate	adcl	12(%esi), %eax
26020Sstevel@tonic-gate.only48:
26030Sstevel@tonic-gate	adcl	16(%esi), %edx
26040Sstevel@tonic-gate.only44:
26050Sstevel@tonic-gate	adcl	20(%esi), %eax
26060Sstevel@tonic-gate.only40:
26070Sstevel@tonic-gate	adcl	24(%esi), %edx
26080Sstevel@tonic-gate.only36:
26090Sstevel@tonic-gate	adcl	28(%esi), %eax
26100Sstevel@tonic-gate.only32:
26110Sstevel@tonic-gate	adcl	32(%esi), %edx
26120Sstevel@tonic-gate.only28:
26130Sstevel@tonic-gate	adcl	36(%esi), %eax
26140Sstevel@tonic-gate.only24:
26150Sstevel@tonic-gate	adcl	40(%esi), %edx
26160Sstevel@tonic-gate.only20:
26170Sstevel@tonic-gate	adcl	44(%esi), %eax
26180Sstevel@tonic-gate.only16:
26190Sstevel@tonic-gate	adcl	48(%esi), %edx
26200Sstevel@tonic-gate.only12:
26210Sstevel@tonic-gate	adcl	52(%esi), %eax
26220Sstevel@tonic-gate.only8:
26230Sstevel@tonic-gate	adcl	56(%esi), %edx
26240Sstevel@tonic-gate.only4:
26250Sstevel@tonic-gate	adcl	60(%esi), %eax	/* We could be adding -1 and -1 with a carry */
26260Sstevel@tonic-gate.only0:
26270Sstevel@tonic-gate	adcl	$0, %eax	/* we could be adding -1 in eax with a carry */
26280Sstevel@tonic-gate	adcl	$0, %eax
26290Sstevel@tonic-gate
26300Sstevel@tonic-gate	addl	$64, %esi
26310Sstevel@tonic-gate	andl	%ecx, %ecx
26320Sstevel@tonic-gate	jnz	.next_iter
26330Sstevel@tonic-gate
26340Sstevel@tonic-gate.ip_ocsum_done:
26350Sstevel@tonic-gate	addl	%eax, %edx
26360Sstevel@tonic-gate	adcl	$0, %edx
26370Sstevel@tonic-gate	movl	%edx, %eax	/* form a 16 bit checksum by */
26380Sstevel@tonic-gate	shrl	$16, %eax	/* adding two halves of 32 bit checksum */
26390Sstevel@tonic-gate	addw	%dx, %ax
26400Sstevel@tonic-gate	adcw	$0, %ax
26410Sstevel@tonic-gate	andl	$0xffff, %eax
26420Sstevel@tonic-gate	popl	%edi		/* restore registers */
26430Sstevel@tonic-gate	popl	%esi
26440Sstevel@tonic-gate	popl	%ebx
26450Sstevel@tonic-gate	leave
26460Sstevel@tonic-gate	ret
26470Sstevel@tonic-gate
26480Sstevel@tonic-gate.ip_csum_notaligned:
26490Sstevel@tonic-gate	xorl	%edi, %edi
26500Sstevel@tonic-gate	movw	(%esi), %di
26510Sstevel@tonic-gate	addl	%edi, %edx
26520Sstevel@tonic-gate	adcl	$0, %edx
26530Sstevel@tonic-gate	addl	$2, %esi
26540Sstevel@tonic-gate	decl	%ecx
26550Sstevel@tonic-gate	jmp	.ip_csum_aligned
26560Sstevel@tonic-gate
26570Sstevel@tonic-gate.less_than_32:
26580Sstevel@tonic-gate	addl	$32, %ecx
26590Sstevel@tonic-gate	testl	$1, %ecx
26600Sstevel@tonic-gate	jz	.size_aligned
26610Sstevel@tonic-gate	andl	$0xfe, %ecx
26620Sstevel@tonic-gate	movzwl	(%esi, %ecx, 2), %edi
26630Sstevel@tonic-gate	addl	%edi, %edx
26640Sstevel@tonic-gate	adcl	$0, %edx
26650Sstevel@tonic-gate.size_aligned:
26660Sstevel@tonic-gate	movl	%ecx, %edi
26670Sstevel@tonic-gate	shrl	$1, %ecx
26680Sstevel@tonic-gate	shl	$1, %edi
26690Sstevel@tonic-gate	subl	$64, %edi
26700Sstevel@tonic-gate	addl	%edi, %esi
26710Sstevel@tonic-gate	movl	$.ip_ocsum_jmptbl, %edi
26720Sstevel@tonic-gate	lea	(%edi, %ecx, 4), %edi
26730Sstevel@tonic-gate	xorl	%ecx, %ecx
26740Sstevel@tonic-gate	clc
26750Sstevel@tonic-gate	jmp 	*(%edi)
26760Sstevel@tonic-gate	SET_SIZE(ip_ocsum)
26770Sstevel@tonic-gate
26780Sstevel@tonic-gate	.data
26790Sstevel@tonic-gate	.align	4
26800Sstevel@tonic-gate
26810Sstevel@tonic-gate.ip_ocsum_jmptbl:
26820Sstevel@tonic-gate	.long	.only0, .only4, .only8, .only12, .only16, .only20
26830Sstevel@tonic-gate	.long	.only24, .only28, .only32, .only36, .only40, .only44
26840Sstevel@tonic-gate	.long	.only48, .only52, .only56, .only60
26850Sstevel@tonic-gate
26860Sstevel@tonic-gate
26870Sstevel@tonic-gate#endif	/* __i386 */
26880Sstevel@tonic-gate#endif	/* __lint */
26890Sstevel@tonic-gate
26900Sstevel@tonic-gate/*
26910Sstevel@tonic-gate * multiply two long numbers and yield a u_longlong_t result, callable from C.
26920Sstevel@tonic-gate * Provided to manipulate hrtime_t values.
26930Sstevel@tonic-gate */
26940Sstevel@tonic-gate#if defined(__lint)
26950Sstevel@tonic-gate
26960Sstevel@tonic-gate/* result = a * b; */
26970Sstevel@tonic-gate
26980Sstevel@tonic-gate/* ARGSUSED */
26990Sstevel@tonic-gateunsigned long long
27000Sstevel@tonic-gatemul32(uint_t a, uint_t b)
27010Sstevel@tonic-gate{ return (0); }
27020Sstevel@tonic-gate
27030Sstevel@tonic-gate#else	/* __lint */
27040Sstevel@tonic-gate
27050Sstevel@tonic-gate#if defined(__amd64)
27060Sstevel@tonic-gate
27070Sstevel@tonic-gate	ENTRY(mul32)
27080Sstevel@tonic-gate	xorl	%edx, %edx	/* XX64 joe, paranoia? */
27090Sstevel@tonic-gate	movl	%edi, %eax
27100Sstevel@tonic-gate	mull	%esi
27110Sstevel@tonic-gate	shlq	$32, %rdx
27120Sstevel@tonic-gate	orq	%rdx, %rax
27130Sstevel@tonic-gate	ret
27140Sstevel@tonic-gate	SET_SIZE(mul32)
27150Sstevel@tonic-gate
27160Sstevel@tonic-gate#elif defined(__i386)
27170Sstevel@tonic-gate
27180Sstevel@tonic-gate	ENTRY(mul32)
27190Sstevel@tonic-gate	movl	8(%esp), %eax
27200Sstevel@tonic-gate	movl	4(%esp), %ecx
27210Sstevel@tonic-gate	mull	%ecx
27220Sstevel@tonic-gate	ret
27230Sstevel@tonic-gate	SET_SIZE(mul32)
27240Sstevel@tonic-gate
27250Sstevel@tonic-gate#endif	/* __i386 */
27260Sstevel@tonic-gate#endif	/* __lint */
27270Sstevel@tonic-gate
27280Sstevel@tonic-gate#if defined(notused)
27290Sstevel@tonic-gate#if defined(__lint)
27300Sstevel@tonic-gate/* ARGSUSED */
27310Sstevel@tonic-gatevoid
27320Sstevel@tonic-gateload_pte64(uint64_t *pte, uint64_t pte_value)
27330Sstevel@tonic-gate{}
27340Sstevel@tonic-gate#else	/* __lint */
27350Sstevel@tonic-gate	.globl load_pte64
27360Sstevel@tonic-gateload_pte64:
27370Sstevel@tonic-gate	movl	4(%esp), %eax
27380Sstevel@tonic-gate	movl	8(%esp), %ecx
27390Sstevel@tonic-gate	movl	12(%esp), %edx
27400Sstevel@tonic-gate	movl	%edx, 4(%eax)
27410Sstevel@tonic-gate	movl	%ecx, (%eax)
27420Sstevel@tonic-gate	ret
27430Sstevel@tonic-gate#endif	/* __lint */
27440Sstevel@tonic-gate#endif	/* notused */
27450Sstevel@tonic-gate
27460Sstevel@tonic-gate#if defined(__lint)
27470Sstevel@tonic-gate
27480Sstevel@tonic-gate/*ARGSUSED*/
27490Sstevel@tonic-gatevoid
27500Sstevel@tonic-gatescan_memory(caddr_t addr, size_t size)
27510Sstevel@tonic-gate{}
27520Sstevel@tonic-gate
27530Sstevel@tonic-gate#else	/* __lint */
27540Sstevel@tonic-gate
27550Sstevel@tonic-gate#if defined(__amd64)
27560Sstevel@tonic-gate
27570Sstevel@tonic-gate	ENTRY(scan_memory)
27580Sstevel@tonic-gate	shrq	$3, %rsi	/* convert %rsi from byte to quadword count */
27590Sstevel@tonic-gate	jz	.scanm_done
27600Sstevel@tonic-gate	movq	%rsi, %rcx	/* move count into rep control register */
27610Sstevel@tonic-gate	movq	%rdi, %rsi	/* move addr into lodsq control reg. */
27620Sstevel@tonic-gate	rep lodsq		/* scan the memory range */
27630Sstevel@tonic-gate.scanm_done:
2764545Skalai	rep;	ret	/* use 2 byte return instruction when branch target */
2765545Skalai			/* AMD Software Optimization Guide - Section 6.2 */
27660Sstevel@tonic-gate	SET_SIZE(scan_memory)
27670Sstevel@tonic-gate
27680Sstevel@tonic-gate#elif defined(__i386)
27690Sstevel@tonic-gate
27700Sstevel@tonic-gate	ENTRY(scan_memory)
27710Sstevel@tonic-gate	pushl	%ecx
27720Sstevel@tonic-gate	pushl	%esi
27730Sstevel@tonic-gate	movl	16(%esp), %ecx	/* move 2nd arg into rep control register */
27740Sstevel@tonic-gate	shrl	$2, %ecx	/* convert from byte count to word count */
27750Sstevel@tonic-gate	jz	.scanm_done
27760Sstevel@tonic-gate	movl	12(%esp), %esi	/* move 1st arg into lodsw control register */
27770Sstevel@tonic-gate	.byte	0xf3		/* rep prefix.  lame assembler.  sigh. */
27780Sstevel@tonic-gate	lodsl
27790Sstevel@tonic-gate.scanm_done:
27800Sstevel@tonic-gate	popl	%esi
27810Sstevel@tonic-gate	popl	%ecx
27820Sstevel@tonic-gate	ret
27830Sstevel@tonic-gate	SET_SIZE(scan_memory)
27840Sstevel@tonic-gate
27850Sstevel@tonic-gate#endif	/* __i386 */
27860Sstevel@tonic-gate#endif	/* __lint */
27870Sstevel@tonic-gate
27880Sstevel@tonic-gate
27890Sstevel@tonic-gate#if defined(__lint)
27900Sstevel@tonic-gate
27910Sstevel@tonic-gate/*ARGSUSED */
27920Sstevel@tonic-gateint
27930Sstevel@tonic-gatelowbit(ulong_t i)
27940Sstevel@tonic-gate{ return (0); }
27950Sstevel@tonic-gate
27960Sstevel@tonic-gate#else	/* __lint */
27970Sstevel@tonic-gate
27980Sstevel@tonic-gate#if defined(__amd64)
27990Sstevel@tonic-gate
28000Sstevel@tonic-gate	ENTRY(lowbit)
28010Sstevel@tonic-gate	movl	$-1, %eax
28020Sstevel@tonic-gate	bsfq	%rdi, %rax
28030Sstevel@tonic-gate	incl	%eax
28040Sstevel@tonic-gate	ret
28050Sstevel@tonic-gate	SET_SIZE(lowbit)
28060Sstevel@tonic-gate
28070Sstevel@tonic-gate#elif defined(__i386)
28080Sstevel@tonic-gate
28090Sstevel@tonic-gate	ENTRY(lowbit)
28100Sstevel@tonic-gate	movl	$-1, %eax
28110Sstevel@tonic-gate	bsfl	4(%esp), %eax
28120Sstevel@tonic-gate	incl	%eax
28130Sstevel@tonic-gate	ret
28140Sstevel@tonic-gate	SET_SIZE(lowbit)
28150Sstevel@tonic-gate
28160Sstevel@tonic-gate#endif	/* __i386 */
28170Sstevel@tonic-gate#endif	/* __lint */
28180Sstevel@tonic-gate
28190Sstevel@tonic-gate#if defined(__lint)
28200Sstevel@tonic-gate
28210Sstevel@tonic-gate/*ARGSUSED*/
28220Sstevel@tonic-gateint
28230Sstevel@tonic-gatehighbit(ulong_t i)
28240Sstevel@tonic-gate{ return (0); }
28250Sstevel@tonic-gate
28260Sstevel@tonic-gate#else	/* __lint */
28270Sstevel@tonic-gate
28280Sstevel@tonic-gate#if defined(__amd64)
28290Sstevel@tonic-gate
28300Sstevel@tonic-gate	ENTRY(highbit)
28310Sstevel@tonic-gate	movl	$-1, %eax
28320Sstevel@tonic-gate	bsrq	%rdi, %rax
28330Sstevel@tonic-gate	incl	%eax
28340Sstevel@tonic-gate	ret
28350Sstevel@tonic-gate	SET_SIZE(highbit)
28360Sstevel@tonic-gate
28370Sstevel@tonic-gate#elif defined(__i386)
28380Sstevel@tonic-gate
28390Sstevel@tonic-gate	ENTRY(highbit)
28400Sstevel@tonic-gate	movl	$-1, %eax
28410Sstevel@tonic-gate	bsrl	4(%esp), %eax
28420Sstevel@tonic-gate	incl	%eax
28430Sstevel@tonic-gate	ret
28440Sstevel@tonic-gate	SET_SIZE(highbit)
28450Sstevel@tonic-gate
28460Sstevel@tonic-gate#endif	/* __i386 */
28470Sstevel@tonic-gate#endif	/* __lint */
28480Sstevel@tonic-gate
28490Sstevel@tonic-gate#if defined(__lint)
28500Sstevel@tonic-gate
28510Sstevel@tonic-gate/*ARGSUSED*/
28520Sstevel@tonic-gateuint64_t
2853770Skucharskrdmsr(uint_t r)
28540Sstevel@tonic-gate{ return (0); }
28550Sstevel@tonic-gate
28560Sstevel@tonic-gate/*ARGSUSED*/
28570Sstevel@tonic-gatevoid
2858770Skucharskwrmsr(uint_t r, const uint64_t val)
28590Sstevel@tonic-gate{}
28600Sstevel@tonic-gate
28611582Skchow/*ARGSUSED*/
28621582Skchowuint64_t
28631582Skchowxrdmsr(uint_t r)
28641582Skchow{ return (0); }
28651582Skchow
28661582Skchow/*ARGSUSED*/
28671582Skchowvoid
28681582Skchowxwrmsr(uint_t r, const uint64_t val)
28691582Skchow{}
28701582Skchow
28710Sstevel@tonic-gatevoid
28720Sstevel@tonic-gateinvalidate_cache(void)
28730Sstevel@tonic-gate{}
28740Sstevel@tonic-gate
2875*13134Skuriakose.kuruvilla@oracle.com/*ARGSUSED*/
2876*13134Skuriakose.kuruvilla@oracle.comuint64_t
2877*13134Skuriakose.kuruvilla@oracle.comget_xcr(uint_t r)
2878*13134Skuriakose.kuruvilla@oracle.com{ return (0); }
2879*13134Skuriakose.kuruvilla@oracle.com
2880*13134Skuriakose.kuruvilla@oracle.com/*ARGSUSED*/
2881*13134Skuriakose.kuruvilla@oracle.comvoid
2882*13134Skuriakose.kuruvilla@oracle.comset_xcr(uint_t r, const uint64_t val)
2883*13134Skuriakose.kuruvilla@oracle.com{}
2884*13134Skuriakose.kuruvilla@oracle.com
28850Sstevel@tonic-gate#else  /* __lint */
28860Sstevel@tonic-gate
28871582Skchow#define	XMSR_ACCESS_VAL		$0x9c5a203a
28881582Skchow
28890Sstevel@tonic-gate#if defined(__amd64)
28903446Smrj
28910Sstevel@tonic-gate	ENTRY(rdmsr)
28920Sstevel@tonic-gate	movl	%edi, %ecx
28930Sstevel@tonic-gate	rdmsr
28940Sstevel@tonic-gate	shlq	$32, %rdx
28950Sstevel@tonic-gate	orq	%rdx, %rax
28960Sstevel@tonic-gate	ret
28970Sstevel@tonic-gate	SET_SIZE(rdmsr)
28980Sstevel@tonic-gate
28990Sstevel@tonic-gate	ENTRY(wrmsr)
2900770Skucharsk	movq	%rsi, %rdx
2901770Skucharsk	shrq	$32, %rdx
2902770Skucharsk	movl	%esi, %eax
29030Sstevel@tonic-gate	movl	%edi, %ecx
29040Sstevel@tonic-gate	wrmsr
29050Sstevel@tonic-gate	ret
29060Sstevel@tonic-gate	SET_SIZE(wrmsr)
29070Sstevel@tonic-gate
29081582Skchow	ENTRY(xrdmsr)
29093446Smrj	pushq	%rbp
29103446Smrj	movq	%rsp, %rbp
29111582Skchow	movl	%edi, %ecx
29121582Skchow	movl	XMSR_ACCESS_VAL, %edi	/* this value is needed to access MSR */
29131582Skchow	rdmsr
29141582Skchow	shlq	$32, %rdx
29151582Skchow	orq	%rdx, %rax
29163446Smrj	leave
29171582Skchow	ret
29181582Skchow	SET_SIZE(xrdmsr)
29191582Skchow
29201582Skchow	ENTRY(xwrmsr)
29213446Smrj	pushq	%rbp
29223446Smrj	movq	%rsp, %rbp
29231582Skchow	movl	%edi, %ecx
29241582Skchow	movl	XMSR_ACCESS_VAL, %edi	/* this value is needed to access MSR */
29251582Skchow	movq	%rsi, %rdx
29261582Skchow	shrq	$32, %rdx
29271582Skchow	movl	%esi, %eax
29281582Skchow	wrmsr
29293446Smrj	leave
29301582Skchow	ret
29311582Skchow	SET_SIZE(xwrmsr)
2932*13134Skuriakose.kuruvilla@oracle.com
2933*13134Skuriakose.kuruvilla@oracle.com	ENTRY(get_xcr)
2934*13134Skuriakose.kuruvilla@oracle.com	movl	%edi, %ecx
2935*13134Skuriakose.kuruvilla@oracle.com	#xgetbv
2936*13134Skuriakose.kuruvilla@oracle.com	.byte	0x0f,0x01,0xd0
2937*13134Skuriakose.kuruvilla@oracle.com	shlq	$32, %rdx
2938*13134Skuriakose.kuruvilla@oracle.com	orq	%rdx, %rax
2939*13134Skuriakose.kuruvilla@oracle.com	ret
2940*13134Skuriakose.kuruvilla@oracle.com	SET_SIZE(get_xcr)
2941*13134Skuriakose.kuruvilla@oracle.com
2942*13134Skuriakose.kuruvilla@oracle.com	ENTRY(set_xcr)
2943*13134Skuriakose.kuruvilla@oracle.com	movq	%rsi, %rdx
2944*13134Skuriakose.kuruvilla@oracle.com	shrq	$32, %rdx
2945*13134Skuriakose.kuruvilla@oracle.com	movl	%esi, %eax
2946*13134Skuriakose.kuruvilla@oracle.com	movl	%edi, %ecx
2947*13134Skuriakose.kuruvilla@oracle.com	#xsetbv
2948*13134Skuriakose.kuruvilla@oracle.com	.byte	0x0f,0x01,0xd1
2949*13134Skuriakose.kuruvilla@oracle.com	ret
2950*13134Skuriakose.kuruvilla@oracle.com	SET_SIZE(set_xcr)
2951*13134Skuriakose.kuruvilla@oracle.com
29520Sstevel@tonic-gate#elif defined(__i386)
29530Sstevel@tonic-gate
29540Sstevel@tonic-gate	ENTRY(rdmsr)
29550Sstevel@tonic-gate	movl	4(%esp), %ecx
29560Sstevel@tonic-gate	rdmsr
29570Sstevel@tonic-gate	ret
29580Sstevel@tonic-gate	SET_SIZE(rdmsr)
29590Sstevel@tonic-gate
29600Sstevel@tonic-gate	ENTRY(wrmsr)
29610Sstevel@tonic-gate	movl	4(%esp), %ecx
2962770Skucharsk	movl	8(%esp), %eax
2963770Skucharsk	movl	12(%esp), %edx
29640Sstevel@tonic-gate	wrmsr
29650Sstevel@tonic-gate	ret
29660Sstevel@tonic-gate	SET_SIZE(wrmsr)
29670Sstevel@tonic-gate
29681582Skchow	ENTRY(xrdmsr)
29693446Smrj	pushl	%ebp
29703446Smrj	movl	%esp, %ebp
29713446Smrj	movl	8(%esp), %ecx
29723446Smrj	pushl	%edi
29731582Skchow	movl	XMSR_ACCESS_VAL, %edi	/* this value is needed to access MSR */
29741582Skchow	rdmsr
29753446Smrj	popl	%edi
29763446Smrj	leave
29771582Skchow	ret
29781582Skchow	SET_SIZE(xrdmsr)
29791582Skchow
29801582Skchow	ENTRY(xwrmsr)
29813446Smrj	pushl	%ebp
29823446Smrj	movl	%esp, %ebp
29833446Smrj	movl	8(%esp), %ecx
29843446Smrj	movl	12(%esp), %eax
29853446Smrj	movl	16(%esp), %edx
29863446Smrj	pushl	%edi
29871582Skchow	movl	XMSR_ACCESS_VAL, %edi	/* this value is needed to access MSR */
29881582Skchow	wrmsr
29893446Smrj	popl	%edi
29903446Smrj	leave
29911582Skchow	ret
29921582Skchow	SET_SIZE(xwrmsr)
29931582Skchow
2994*13134Skuriakose.kuruvilla@oracle.com	ENTRY(get_xcr)
2995*13134Skuriakose.kuruvilla@oracle.com	movl	4(%esp), %ecx
2996*13134Skuriakose.kuruvilla@oracle.com	#xgetbv
2997*13134Skuriakose.kuruvilla@oracle.com	.byte	0x0f,0x01,0xd0
2998*13134Skuriakose.kuruvilla@oracle.com	ret
2999*13134Skuriakose.kuruvilla@oracle.com	SET_SIZE(get_xcr)
3000*13134Skuriakose.kuruvilla@oracle.com
3001*13134Skuriakose.kuruvilla@oracle.com	ENTRY(set_xcr)
3002*13134Skuriakose.kuruvilla@oracle.com	movl	4(%esp), %ecx
3003*13134Skuriakose.kuruvilla@oracle.com	movl	8(%esp), %eax
3004*13134Skuriakose.kuruvilla@oracle.com	movl	12(%esp), %edx
3005*13134Skuriakose.kuruvilla@oracle.com	#xsetbv
3006*13134Skuriakose.kuruvilla@oracle.com	.byte	0x0f,0x01,0xd1
3007*13134Skuriakose.kuruvilla@oracle.com	ret
3008*13134Skuriakose.kuruvilla@oracle.com	SET_SIZE(set_xcr)
3009*13134Skuriakose.kuruvilla@oracle.com
30100Sstevel@tonic-gate#endif	/* __i386 */
30110Sstevel@tonic-gate
30120Sstevel@tonic-gate	ENTRY(invalidate_cache)
30130Sstevel@tonic-gate	wbinvd
30140Sstevel@tonic-gate	ret
30150Sstevel@tonic-gate	SET_SIZE(invalidate_cache)
30160Sstevel@tonic-gate
30170Sstevel@tonic-gate#endif	/* __lint */
30180Sstevel@tonic-gate
30190Sstevel@tonic-gate#if defined(__lint)
30200Sstevel@tonic-gate
30210Sstevel@tonic-gate/*ARGSUSED*/
30223446Smrjvoid
30233446Smrjgetcregs(struct cregs *crp)
30240Sstevel@tonic-gate{}
30250Sstevel@tonic-gate
30260Sstevel@tonic-gate#else	/* __lint */
30270Sstevel@tonic-gate
30280Sstevel@tonic-gate#if defined(__amd64)
30290Sstevel@tonic-gate
30303446Smrj	ENTRY_NP(getcregs)
30315084Sjohnlev#if defined(__xpv)
30325084Sjohnlev	/*
30335084Sjohnlev	 * Only a few of the hardware control registers or descriptor tables
30345084Sjohnlev	 * are directly accessible to us, so just zero the structure.
30355084Sjohnlev	 *
30365084Sjohnlev	 * XXPV	Perhaps it would be helpful for the hypervisor to return
30375084Sjohnlev	 *	virtualized versions of these for post-mortem use.
30385084Sjohnlev	 *	(Need to reevaluate - perhaps it already does!)
30395084Sjohnlev	 */
30405084Sjohnlev	pushq	%rdi		/* save *crp */
30415084Sjohnlev	movq	$CREGSZ, %rsi
30425084Sjohnlev	call	bzero
30435084Sjohnlev	popq	%rdi
30445084Sjohnlev
30455084Sjohnlev	/*
30465084Sjohnlev	 * Dump what limited information we can
30475084Sjohnlev	 */
30485084Sjohnlev	movq	%cr0, %rax
30495084Sjohnlev	movq	%rax, CREG_CR0(%rdi)	/* cr0 */
30505084Sjohnlev	movq	%cr2, %rax
30515084Sjohnlev	movq	%rax, CREG_CR2(%rdi)	/* cr2 */
30525084Sjohnlev	movq	%cr3, %rax
30535084Sjohnlev	movq	%rax, CREG_CR3(%rdi)	/* cr3 */
30545084Sjohnlev	movq	%cr4, %rax
30555084Sjohnlev	movq	%rax, CREG_CR4(%rdi)	/* cr4 */
30565084Sjohnlev
30575084Sjohnlev#else	/* __xpv */
30583446Smrj
30590Sstevel@tonic-gate#define	GETMSR(r, off, d)	\
30600Sstevel@tonic-gate	movl	$r, %ecx;	\
30610Sstevel@tonic-gate	rdmsr;			\
30620Sstevel@tonic-gate	movl	%eax, off(d);	\
30630Sstevel@tonic-gate	movl	%edx, off+4(d)
30640Sstevel@tonic-gate
30650Sstevel@tonic-gate	xorl	%eax, %eax
30660Sstevel@tonic-gate	movq	%rax, CREG_GDT+8(%rdi)
30670Sstevel@tonic-gate	sgdt	CREG_GDT(%rdi)		/* 10 bytes */
30680Sstevel@tonic-gate	movq	%rax, CREG_IDT+8(%rdi)
30690Sstevel@tonic-gate	sidt	CREG_IDT(%rdi)		/* 10 bytes */
30700Sstevel@tonic-gate	movq	%rax, CREG_LDT(%rdi)
30710Sstevel@tonic-gate	sldt	CREG_LDT(%rdi)		/* 2 bytes */
30720Sstevel@tonic-gate	movq	%rax, CREG_TASKR(%rdi)
30730Sstevel@tonic-gate	str	CREG_TASKR(%rdi)	/* 2 bytes */
30740Sstevel@tonic-gate	movq	%cr0, %rax
30750Sstevel@tonic-gate	movq	%rax, CREG_CR0(%rdi)	/* cr0 */
30760Sstevel@tonic-gate	movq	%cr2, %rax
30770Sstevel@tonic-gate	movq	%rax, CREG_CR2(%rdi)	/* cr2 */
30780Sstevel@tonic-gate	movq	%cr3, %rax
30790Sstevel@tonic-gate	movq	%rax, CREG_CR3(%rdi)	/* cr3 */
30800Sstevel@tonic-gate	movq	%cr4, %rax
30813446Smrj	movq	%rax, CREG_CR4(%rdi)	/* cr4 */
30820Sstevel@tonic-gate	movq	%cr8, %rax
30830Sstevel@tonic-gate	movq	%rax, CREG_CR8(%rdi)	/* cr8 */
30840Sstevel@tonic-gate	GETMSR(MSR_AMD_KGSBASE, CREG_KGSBASE, %rdi)
30850Sstevel@tonic-gate	GETMSR(MSR_AMD_EFER, CREG_EFER, %rdi)
30865084Sjohnlev#endif	/* __xpv */
30873446Smrj	ret
30880Sstevel@tonic-gate	SET_SIZE(getcregs)
30890Sstevel@tonic-gate
30900Sstevel@tonic-gate#undef GETMSR
30910Sstevel@tonic-gate
30920Sstevel@tonic-gate#elif defined(__i386)
30930Sstevel@tonic-gate
30940Sstevel@tonic-gate	ENTRY_NP(getcregs)
30955084Sjohnlev#if defined(__xpv)
30965084Sjohnlev	/*
30975084Sjohnlev	 * Only a few of the hardware control registers or descriptor tables
30985084Sjohnlev	 * are directly accessible to us, so just zero the structure.
30995084Sjohnlev	 *
31005084Sjohnlev	 * XXPV	Perhaps it would be helpful for the hypervisor to return
31015084Sjohnlev	 *	virtualized versions of these for post-mortem use.
31025084Sjohnlev	 *	(Need to reevaluate - perhaps it already does!)
31035084Sjohnlev	 */
31045084Sjohnlev	movl	4(%esp), %edx
31055084Sjohnlev	pushl	$CREGSZ
31065084Sjohnlev	pushl	%edx
31075084Sjohnlev	call	bzero
31085084Sjohnlev	addl	$8, %esp
31095084Sjohnlev	movl	4(%esp), %edx
31105084Sjohnlev
31115084Sjohnlev	/*
31125084Sjohnlev	 * Dump what limited information we can
31135084Sjohnlev	 */
31145084Sjohnlev	movl	%cr0, %eax
31155084Sjohnlev	movl	%eax, CREG_CR0(%edx)	/* cr0 */
31165084Sjohnlev	movl	%cr2, %eax
31175084Sjohnlev	movl	%eax, CREG_CR2(%edx)	/* cr2 */
31185084Sjohnlev	movl	%cr3, %eax
31195084Sjohnlev	movl	%eax, CREG_CR3(%edx)	/* cr3 */
31205084Sjohnlev	movl	%cr4, %eax
31215084Sjohnlev	movl	%eax, CREG_CR4(%edx)	/* cr4 */
31225084Sjohnlev
31235084Sjohnlev#else	/* __xpv */
31245084Sjohnlev
31250Sstevel@tonic-gate	movl	4(%esp), %edx
31260Sstevel@tonic-gate	movw	$0, CREG_GDT+6(%edx)
31270Sstevel@tonic-gate	movw	$0, CREG_IDT+6(%edx)
31280Sstevel@tonic-gate	sgdt	CREG_GDT(%edx)		/* gdt */
31290Sstevel@tonic-gate	sidt	CREG_IDT(%edx)		/* idt */
31300Sstevel@tonic-gate	sldt	CREG_LDT(%edx)		/* ldt */
31310Sstevel@tonic-gate	str	CREG_TASKR(%edx)	/* task */
31320Sstevel@tonic-gate	movl	%cr0, %eax
31330Sstevel@tonic-gate	movl	%eax, CREG_CR0(%edx)	/* cr0 */
31340Sstevel@tonic-gate	movl	%cr2, %eax
31350Sstevel@tonic-gate	movl	%eax, CREG_CR2(%edx)	/* cr2 */
31360Sstevel@tonic-gate	movl	%cr3, %eax
31370Sstevel@tonic-gate	movl	%eax, CREG_CR3(%edx)	/* cr3 */
313812826Skuriakose.kuruvilla@oracle.com	bt	$X86FSET_LARGEPAGE, x86_featureset
313912826Skuriakose.kuruvilla@oracle.com	jnc	.nocr4
31400Sstevel@tonic-gate	movl	%cr4, %eax
31410Sstevel@tonic-gate	movl	%eax, CREG_CR4(%edx)	/* cr4 */
31420Sstevel@tonic-gate	jmp	.skip
31430Sstevel@tonic-gate.nocr4:
31440Sstevel@tonic-gate	movl	$0, CREG_CR4(%edx)
31450Sstevel@tonic-gate.skip:
31465084Sjohnlev#endif
31473446Smrj	ret
31480Sstevel@tonic-gate	SET_SIZE(getcregs)
31490Sstevel@tonic-gate
31500Sstevel@tonic-gate#endif	/* __i386 */
31510Sstevel@tonic-gate#endif	/* __lint */
31520Sstevel@tonic-gate
31530Sstevel@tonic-gate
31540Sstevel@tonic-gate/*
31550Sstevel@tonic-gate * A panic trigger is a word which is updated atomically and can only be set
31560Sstevel@tonic-gate * once.  We atomically store 0xDEFACEDD and load the old value.  If the
31570Sstevel@tonic-gate * previous value was 0, we succeed and return 1; otherwise return 0.
31580Sstevel@tonic-gate * This allows a partially corrupt trigger to still trigger correctly.  DTrace
31590Sstevel@tonic-gate * has its own version of this function to allow it to panic correctly from
31600Sstevel@tonic-gate * probe context.
31610Sstevel@tonic-gate */
31620Sstevel@tonic-gate#if defined(__lint)
31630Sstevel@tonic-gate
31640Sstevel@tonic-gate/*ARGSUSED*/
31650Sstevel@tonic-gateint
31660Sstevel@tonic-gatepanic_trigger(int *tp)
31670Sstevel@tonic-gate{ return (0); }
31680Sstevel@tonic-gate
31690Sstevel@tonic-gate/*ARGSUSED*/
31700Sstevel@tonic-gateint
31710Sstevel@tonic-gatedtrace_panic_trigger(int *tp)
31720Sstevel@tonic-gate{ return (0); }
31730Sstevel@tonic-gate
31740Sstevel@tonic-gate#else	/* __lint */
31750Sstevel@tonic-gate
31760Sstevel@tonic-gate#if defined(__amd64)
31770Sstevel@tonic-gate
31780Sstevel@tonic-gate	ENTRY_NP(panic_trigger)
31790Sstevel@tonic-gate	xorl	%eax, %eax
31800Sstevel@tonic-gate	movl	$0xdefacedd, %edx
31810Sstevel@tonic-gate	lock
31820Sstevel@tonic-gate	  xchgl	%edx, (%rdi)
31830Sstevel@tonic-gate	cmpl	$0, %edx
31840Sstevel@tonic-gate	je	0f
31850Sstevel@tonic-gate	movl	$0, %eax
31860Sstevel@tonic-gate	ret
31870Sstevel@tonic-gate0:	movl	$1, %eax
31880Sstevel@tonic-gate	ret
31890Sstevel@tonic-gate	SET_SIZE(panic_trigger)
31900Sstevel@tonic-gate
31910Sstevel@tonic-gate	ENTRY_NP(dtrace_panic_trigger)
31920Sstevel@tonic-gate	xorl	%eax, %eax
31930Sstevel@tonic-gate	movl	$0xdefacedd, %edx
31940Sstevel@tonic-gate	lock
31950Sstevel@tonic-gate	  xchgl	%edx, (%rdi)
31960Sstevel@tonic-gate	cmpl	$0, %edx
31970Sstevel@tonic-gate	je	0f
31980Sstevel@tonic-gate	movl	$0, %eax
31990Sstevel@tonic-gate	ret
32000Sstevel@tonic-gate0:	movl	$1, %eax
32010Sstevel@tonic-gate	ret
32020Sstevel@tonic-gate	SET_SIZE(dtrace_panic_trigger)
32030Sstevel@tonic-gate
32040Sstevel@tonic-gate#elif defined(__i386)
32050Sstevel@tonic-gate
32060Sstevel@tonic-gate	ENTRY_NP(panic_trigger)
32070Sstevel@tonic-gate	movl	4(%esp), %edx		/ %edx = address of trigger
32080Sstevel@tonic-gate	movl	$0xdefacedd, %eax	/ %eax = 0xdefacedd
32090Sstevel@tonic-gate	lock				/ assert lock
32100Sstevel@tonic-gate	xchgl %eax, (%edx)		/ exchange %eax and the trigger
32110Sstevel@tonic-gate	cmpl	$0, %eax		/ if (%eax == 0x0)
32120Sstevel@tonic-gate	je	0f			/   return (1);
32130Sstevel@tonic-gate	movl	$0, %eax		/ else
32140Sstevel@tonic-gate	ret				/   return (0);
32150Sstevel@tonic-gate0:	movl	$1, %eax
32160Sstevel@tonic-gate	ret
32170Sstevel@tonic-gate	SET_SIZE(panic_trigger)
32180Sstevel@tonic-gate
32190Sstevel@tonic-gate	ENTRY_NP(dtrace_panic_trigger)
32200Sstevel@tonic-gate	movl	4(%esp), %edx		/ %edx = address of trigger
32210Sstevel@tonic-gate	movl	$0xdefacedd, %eax	/ %eax = 0xdefacedd
32220Sstevel@tonic-gate	lock				/ assert lock
32230Sstevel@tonic-gate	xchgl %eax, (%edx)		/ exchange %eax and the trigger
32240Sstevel@tonic-gate	cmpl	$0, %eax		/ if (%eax == 0x0)
32250Sstevel@tonic-gate	je	0f			/   return (1);
32260Sstevel@tonic-gate	movl	$0, %eax		/ else
32270Sstevel@tonic-gate	ret				/   return (0);
32280Sstevel@tonic-gate0:	movl	$1, %eax
32290Sstevel@tonic-gate	ret
32300Sstevel@tonic-gate	SET_SIZE(dtrace_panic_trigger)
32310Sstevel@tonic-gate
32320Sstevel@tonic-gate#endif	/* __i386 */
32330Sstevel@tonic-gate#endif	/* __lint */
32340Sstevel@tonic-gate
32350Sstevel@tonic-gate/*
32360Sstevel@tonic-gate * The panic() and cmn_err() functions invoke vpanic() as a common entry point
32370Sstevel@tonic-gate * into the panic code implemented in panicsys().  vpanic() is responsible
32380Sstevel@tonic-gate * for passing through the format string and arguments, and constructing a
32390Sstevel@tonic-gate * regs structure on the stack into which it saves the current register
32400Sstevel@tonic-gate * values.  If we are not dying due to a fatal trap, these registers will
32410Sstevel@tonic-gate * then be preserved in panicbuf as the current processor state.  Before
32420Sstevel@tonic-gate * invoking panicsys(), vpanic() activates the first panic trigger (see
32430Sstevel@tonic-gate * common/os/panic.c) and switches to the panic_stack if successful.  Note that
32440Sstevel@tonic-gate * DTrace takes a slightly different panic path if it must panic from probe
32450Sstevel@tonic-gate * context.  Instead of calling panic, it calls into dtrace_vpanic(), which
32460Sstevel@tonic-gate * sets up the initial stack as vpanic does, calls dtrace_panic_trigger(), and
32470Sstevel@tonic-gate * branches back into vpanic().
32480Sstevel@tonic-gate */
32490Sstevel@tonic-gate#if defined(__lint)
32500Sstevel@tonic-gate
32510Sstevel@tonic-gate/*ARGSUSED*/
32520Sstevel@tonic-gatevoid
32530Sstevel@tonic-gatevpanic(const char *format, va_list alist)
32540Sstevel@tonic-gate{}
32550Sstevel@tonic-gate
32560Sstevel@tonic-gate/*ARGSUSED*/
32570Sstevel@tonic-gatevoid
32580Sstevel@tonic-gatedtrace_vpanic(const char *format, va_list alist)
32590Sstevel@tonic-gate{}
32600Sstevel@tonic-gate
32610Sstevel@tonic-gate#else	/* __lint */
32620Sstevel@tonic-gate
32630Sstevel@tonic-gate#if defined(__amd64)
32640Sstevel@tonic-gate
32650Sstevel@tonic-gate	ENTRY_NP(vpanic)			/* Initial stack layout: */
32660Sstevel@tonic-gate
32670Sstevel@tonic-gate	pushq	%rbp				/* | %rip | 	0x60	*/
32680Sstevel@tonic-gate	movq	%rsp, %rbp			/* | %rbp |	0x58	*/
32690Sstevel@tonic-gate	pushfq					/* | rfl  |	0x50	*/
32700Sstevel@tonic-gate	pushq	%r11				/* | %r11 |	0x48	*/
32710Sstevel@tonic-gate	pushq	%r10				/* | %r10 |	0x40	*/
32720Sstevel@tonic-gate	pushq	%rbx				/* | %rbx |	0x38	*/
32730Sstevel@tonic-gate	pushq	%rax				/* | %rax |	0x30	*/
32740Sstevel@tonic-gate	pushq	%r9				/* | %r9  |	0x28	*/
32750Sstevel@tonic-gate	pushq	%r8				/* | %r8  |	0x20	*/
32760Sstevel@tonic-gate	pushq	%rcx				/* | %rcx |	0x18	*/
32770Sstevel@tonic-gate	pushq	%rdx				/* | %rdx |	0x10	*/
32780Sstevel@tonic-gate	pushq	%rsi				/* | %rsi |	0x8 alist */
32790Sstevel@tonic-gate	pushq	%rdi				/* | %rdi |	0x0 format */
32800Sstevel@tonic-gate
32810Sstevel@tonic-gate	movq	%rsp, %rbx			/* %rbx = current %rsp */
32820Sstevel@tonic-gate
32830Sstevel@tonic-gate	leaq	panic_quiesce(%rip), %rdi	/* %rdi = &panic_quiesce */
32840Sstevel@tonic-gate	call	panic_trigger			/* %eax = panic_trigger() */
32850Sstevel@tonic-gate
32860Sstevel@tonic-gatevpanic_common:
32871784Sgavinm	/*
32881784Sgavinm	 * The panic_trigger result is in %eax from the call above, and
32891784Sgavinm	 * dtrace_panic places it in %eax before branching here.
32901784Sgavinm	 * The rdmsr instructions that follow below will clobber %eax so
32911784Sgavinm	 * we stash the panic_trigger result in %r11d.
32921784Sgavinm	 */
32931784Sgavinm	movl	%eax, %r11d
32941784Sgavinm	cmpl	$0, %r11d
32950Sstevel@tonic-gate	je	0f
32960Sstevel@tonic-gate
32970Sstevel@tonic-gate	/*
32980Sstevel@tonic-gate	 * If panic_trigger() was successful, we are the first to initiate a
32990Sstevel@tonic-gate	 * panic: we now switch to the reserved panic_stack before continuing.
33000Sstevel@tonic-gate	 */
33010Sstevel@tonic-gate	leaq	panic_stack(%rip), %rsp
33020Sstevel@tonic-gate	addq	$PANICSTKSIZE, %rsp
33030Sstevel@tonic-gate0:	subq	$REGSIZE, %rsp
33040Sstevel@tonic-gate	/*
33050Sstevel@tonic-gate	 * Now that we've got everything set up, store the register values as
33060Sstevel@tonic-gate	 * they were when we entered vpanic() to the designated location in
33070Sstevel@tonic-gate	 * the regs structure we allocated on the stack.
33080Sstevel@tonic-gate	 */
33090Sstevel@tonic-gate	movq	0x0(%rbx), %rcx
33100Sstevel@tonic-gate	movq	%rcx, REGOFF_RDI(%rsp)
33110Sstevel@tonic-gate	movq	0x8(%rbx), %rcx
33120Sstevel@tonic-gate	movq	%rcx, REGOFF_RSI(%rsp)
33130Sstevel@tonic-gate	movq	0x10(%rbx), %rcx
33140Sstevel@tonic-gate	movq	%rcx, REGOFF_RDX(%rsp)
33150Sstevel@tonic-gate	movq	0x18(%rbx), %rcx
33160Sstevel@tonic-gate	movq	%rcx, REGOFF_RCX(%rsp)
33170Sstevel@tonic-gate	movq	0x20(%rbx), %rcx
33180Sstevel@tonic-gate
33190Sstevel@tonic-gate	movq	%rcx, REGOFF_R8(%rsp)
33200Sstevel@tonic-gate	movq	0x28(%rbx), %rcx
33210Sstevel@tonic-gate	movq	%rcx, REGOFF_R9(%rsp)
33220Sstevel@tonic-gate	movq	0x30(%rbx), %rcx
33230Sstevel@tonic-gate	movq	%rcx, REGOFF_RAX(%rsp)
33240Sstevel@tonic-gate	movq	0x38(%rbx), %rcx
33252195Ssethg	movq	%rcx, REGOFF_RBX(%rsp)
33260Sstevel@tonic-gate	movq	0x58(%rbx), %rcx
33270Sstevel@tonic-gate
33280Sstevel@tonic-gate	movq	%rcx, REGOFF_RBP(%rsp)
33290Sstevel@tonic-gate	movq	0x40(%rbx), %rcx
33300Sstevel@tonic-gate	movq	%rcx, REGOFF_R10(%rsp)
33310Sstevel@tonic-gate	movq	0x48(%rbx), %rcx
33320Sstevel@tonic-gate	movq	%rcx, REGOFF_R11(%rsp)
33330Sstevel@tonic-gate	movq	%r12, REGOFF_R12(%rsp)
33340Sstevel@tonic-gate
33350Sstevel@tonic-gate	movq	%r13, REGOFF_R13(%rsp)
33360Sstevel@tonic-gate	movq	%r14, REGOFF_R14(%rsp)
33370Sstevel@tonic-gate	movq	%r15, REGOFF_R15(%rsp)
33380Sstevel@tonic-gate
33390Sstevel@tonic-gate	xorl	%ecx, %ecx
33400Sstevel@tonic-gate	movw	%ds, %cx
33410Sstevel@tonic-gate	movq	%rcx, REGOFF_DS(%rsp)
33420Sstevel@tonic-gate	movw	%es, %cx
33430Sstevel@tonic-gate	movq	%rcx, REGOFF_ES(%rsp)
33440Sstevel@tonic-gate	movw	%fs, %cx
33450Sstevel@tonic-gate	movq	%rcx, REGOFF_FS(%rsp)
33460Sstevel@tonic-gate	movw	%gs, %cx
33470Sstevel@tonic-gate	movq	%rcx, REGOFF_GS(%rsp)
33480Sstevel@tonic-gate
33490Sstevel@tonic-gate	movq	$0, REGOFF_TRAPNO(%rsp)
33500Sstevel@tonic-gate
33510Sstevel@tonic-gate	movq	$0, REGOFF_ERR(%rsp)
33520Sstevel@tonic-gate	leaq	vpanic(%rip), %rcx
33530Sstevel@tonic-gate	movq	%rcx, REGOFF_RIP(%rsp)
33540Sstevel@tonic-gate	movw	%cs, %cx
33550Sstevel@tonic-gate	movzwq	%cx, %rcx
33560Sstevel@tonic-gate	movq	%rcx, REGOFF_CS(%rsp)
33570Sstevel@tonic-gate	movq	0x50(%rbx), %rcx
33580Sstevel@tonic-gate	movq	%rcx, REGOFF_RFL(%rsp)
33590Sstevel@tonic-gate	movq	%rbx, %rcx
33600Sstevel@tonic-gate	addq	$0x60, %rcx
33610Sstevel@tonic-gate	movq	%rcx, REGOFF_RSP(%rsp)
33620Sstevel@tonic-gate	movw	%ss, %cx
33630Sstevel@tonic-gate	movzwq	%cx, %rcx
33640Sstevel@tonic-gate	movq	%rcx, REGOFF_SS(%rsp)
33650Sstevel@tonic-gate
33660Sstevel@tonic-gate	/*
33670Sstevel@tonic-gate	 * panicsys(format, alist, rp, on_panic_stack)
33680Sstevel@tonic-gate	 */
33690Sstevel@tonic-gate	movq	REGOFF_RDI(%rsp), %rdi		/* format */
33700Sstevel@tonic-gate	movq	REGOFF_RSI(%rsp), %rsi		/* alist */
33710Sstevel@tonic-gate	movq	%rsp, %rdx			/* struct regs */
33721784Sgavinm	movl	%r11d, %ecx			/* on_panic_stack */
33730Sstevel@tonic-gate	call	panicsys
33740Sstevel@tonic-gate	addq	$REGSIZE, %rsp
33750Sstevel@tonic-gate	popq	%rdi
33760Sstevel@tonic-gate	popq	%rsi
33770Sstevel@tonic-gate	popq	%rdx
33780Sstevel@tonic-gate	popq	%rcx
33790Sstevel@tonic-gate	popq	%r8
33800Sstevel@tonic-gate	popq	%r9
33810Sstevel@tonic-gate	popq	%rax
33820Sstevel@tonic-gate	popq	%rbx
33830Sstevel@tonic-gate	popq	%r10
33840Sstevel@tonic-gate	popq	%r11
33850Sstevel@tonic-gate	popfq
33860Sstevel@tonic-gate	leave
33870Sstevel@tonic-gate	ret
33880Sstevel@tonic-gate	SET_SIZE(vpanic)
33890Sstevel@tonic-gate
33900Sstevel@tonic-gate	ENTRY_NP(dtrace_vpanic)			/* Initial stack layout: */
33910Sstevel@tonic-gate
33920Sstevel@tonic-gate	pushq	%rbp				/* | %rip | 	0x60	*/
33930Sstevel@tonic-gate	movq	%rsp, %rbp			/* | %rbp |	0x58	*/
33940Sstevel@tonic-gate	pushfq					/* | rfl  |	0x50	*/
33950Sstevel@tonic-gate	pushq	%r11				/* | %r11 |	0x48	*/
33960Sstevel@tonic-gate	pushq	%r10				/* | %r10 |	0x40	*/
33970Sstevel@tonic-gate	pushq	%rbx				/* | %rbx |	0x38	*/
33980Sstevel@tonic-gate	pushq	%rax				/* | %rax |	0x30	*/
33990Sstevel@tonic-gate	pushq	%r9				/* | %r9  |	0x28	*/
34000Sstevel@tonic-gate	pushq	%r8				/* | %r8  |	0x20	*/
34010Sstevel@tonic-gate	pushq	%rcx				/* | %rcx |	0x18	*/
34020Sstevel@tonic-gate	pushq	%rdx				/* | %rdx |	0x10	*/
34030Sstevel@tonic-gate	pushq	%rsi				/* | %rsi |	0x8 alist */
34040Sstevel@tonic-gate	pushq	%rdi				/* | %rdi |	0x0 format */
34050Sstevel@tonic-gate
34060Sstevel@tonic-gate	movq	%rsp, %rbx			/* %rbx = current %rsp */
34070Sstevel@tonic-gate
34080Sstevel@tonic-gate	leaq	panic_quiesce(%rip), %rdi	/* %rdi = &panic_quiesce */
34090Sstevel@tonic-gate	call	dtrace_panic_trigger	/* %eax = dtrace_panic_trigger() */
34100Sstevel@tonic-gate	jmp	vpanic_common
34110Sstevel@tonic-gate
34120Sstevel@tonic-gate	SET_SIZE(dtrace_vpanic)
34130Sstevel@tonic-gate
34140Sstevel@tonic-gate#elif defined(__i386)
34150Sstevel@tonic-gate
34160Sstevel@tonic-gate	ENTRY_NP(vpanic)			/ Initial stack layout:
34170Sstevel@tonic-gate
34180Sstevel@tonic-gate	pushl	%ebp				/ | %eip | 20
34190Sstevel@tonic-gate	movl	%esp, %ebp			/ | %ebp | 16
34200Sstevel@tonic-gate	pushl	%eax				/ | %eax | 12
34210Sstevel@tonic-gate	pushl	%ebx				/ | %ebx |  8
34220Sstevel@tonic-gate	pushl	%ecx				/ | %ecx |  4
34230Sstevel@tonic-gate	pushl	%edx				/ | %edx |  0
34240Sstevel@tonic-gate
34250Sstevel@tonic-gate	movl	%esp, %ebx			/ %ebx = current stack pointer
34260Sstevel@tonic-gate
34270Sstevel@tonic-gate	lea	panic_quiesce, %eax		/ %eax = &panic_quiesce
34280Sstevel@tonic-gate	pushl	%eax				/ push &panic_quiesce
34290Sstevel@tonic-gate	call	panic_trigger			/ %eax = panic_trigger()
34300Sstevel@tonic-gate	addl	$4, %esp			/ reset stack pointer
34310Sstevel@tonic-gate
34320Sstevel@tonic-gatevpanic_common:
34330Sstevel@tonic-gate	cmpl	$0, %eax			/ if (%eax == 0)
34340Sstevel@tonic-gate	je	0f				/   goto 0f;
34350Sstevel@tonic-gate
34360Sstevel@tonic-gate	/*
34370Sstevel@tonic-gate	 * If panic_trigger() was successful, we are the first to initiate a
34380Sstevel@tonic-gate	 * panic: we now switch to the reserved panic_stack before continuing.
34390Sstevel@tonic-gate	 */
34400Sstevel@tonic-gate	lea	panic_stack, %esp		/ %esp  = panic_stack
34410Sstevel@tonic-gate	addl	$PANICSTKSIZE, %esp		/ %esp += PANICSTKSIZE
34420Sstevel@tonic-gate
34430Sstevel@tonic-gate0:	subl	$REGSIZE, %esp			/ allocate struct regs
34440Sstevel@tonic-gate
34450Sstevel@tonic-gate	/*
34460Sstevel@tonic-gate	 * Now that we've got everything set up, store the register values as
34470Sstevel@tonic-gate	 * they were when we entered vpanic() to the designated location in
34480Sstevel@tonic-gate	 * the regs structure we allocated on the stack.
34490Sstevel@tonic-gate	 */
34500Sstevel@tonic-gate#if !defined(__GNUC_AS__)
34510Sstevel@tonic-gate	movw	%gs, %edx
34520Sstevel@tonic-gate	movl	%edx, REGOFF_GS(%esp)
34530Sstevel@tonic-gate	movw	%fs, %edx
34540Sstevel@tonic-gate	movl	%edx, REGOFF_FS(%esp)
34550Sstevel@tonic-gate	movw	%es, %edx
34560Sstevel@tonic-gate	movl	%edx, REGOFF_ES(%esp)
34570Sstevel@tonic-gate	movw	%ds, %edx
34580Sstevel@tonic-gate	movl	%edx, REGOFF_DS(%esp)
34590Sstevel@tonic-gate#else	/* __GNUC_AS__ */
34600Sstevel@tonic-gate	mov	%gs, %edx
34610Sstevel@tonic-gate	mov	%edx, REGOFF_GS(%esp)
34620Sstevel@tonic-gate	mov	%fs, %edx
34630Sstevel@tonic-gate	mov	%edx, REGOFF_FS(%esp)
34640Sstevel@tonic-gate	mov	%es, %edx
34650Sstevel@tonic-gate	mov	%edx, REGOFF_ES(%esp)
34660Sstevel@tonic-gate	mov	%ds, %edx
34670Sstevel@tonic-gate	mov	%edx, REGOFF_DS(%esp)
34680Sstevel@tonic-gate#endif	/* __GNUC_AS__ */
34690Sstevel@tonic-gate	movl	%edi, REGOFF_EDI(%esp)
34700Sstevel@tonic-gate	movl	%esi, REGOFF_ESI(%esp)
34710Sstevel@tonic-gate	movl	16(%ebx), %ecx
34720Sstevel@tonic-gate	movl	%ecx, REGOFF_EBP(%esp)
34730Sstevel@tonic-gate	movl	%ebx, %ecx
34740Sstevel@tonic-gate	addl	$20, %ecx
34750Sstevel@tonic-gate	movl	%ecx, REGOFF_ESP(%esp)
34760Sstevel@tonic-gate	movl	8(%ebx), %ecx
34770Sstevel@tonic-gate	movl	%ecx, REGOFF_EBX(%esp)
34780Sstevel@tonic-gate	movl	0(%ebx), %ecx
34790Sstevel@tonic-gate	movl	%ecx, REGOFF_EDX(%esp)
34800Sstevel@tonic-gate	movl	4(%ebx), %ecx
34810Sstevel@tonic-gate	movl	%ecx, REGOFF_ECX(%esp)
34820Sstevel@tonic-gate	movl	12(%ebx), %ecx
34830Sstevel@tonic-gate	movl	%ecx, REGOFF_EAX(%esp)
34840Sstevel@tonic-gate	movl	$0, REGOFF_TRAPNO(%esp)
34850Sstevel@tonic-gate	movl	$0, REGOFF_ERR(%esp)
34860Sstevel@tonic-gate	lea	vpanic, %ecx
34870Sstevel@tonic-gate	movl	%ecx, REGOFF_EIP(%esp)
34880Sstevel@tonic-gate#if !defined(__GNUC_AS__)
34890Sstevel@tonic-gate	movw	%cs, %edx
34900Sstevel@tonic-gate#else	/* __GNUC_AS__ */
34910Sstevel@tonic-gate	mov	%cs, %edx
34920Sstevel@tonic-gate#endif	/* __GNUC_AS__ */
34930Sstevel@tonic-gate	movl	%edx, REGOFF_CS(%esp)
34940Sstevel@tonic-gate	pushfl
34950Sstevel@tonic-gate	popl	%ecx
34965084Sjohnlev#if defined(__xpv)
34975084Sjohnlev	/*
34985084Sjohnlev	 * Synthesize the PS_IE bit from the event mask bit
34995084Sjohnlev	 */
35005084Sjohnlev	CURTHREAD(%edx)
35015084Sjohnlev	KPREEMPT_DISABLE(%edx)
35025084Sjohnlev	EVENT_MASK_TO_IE(%edx, %ecx)
35035084Sjohnlev	CURTHREAD(%edx)
35045084Sjohnlev	KPREEMPT_ENABLE_NOKP(%edx)
35055084Sjohnlev#endif
35060Sstevel@tonic-gate	movl	%ecx, REGOFF_EFL(%esp)
35070Sstevel@tonic-gate	movl	$0, REGOFF_UESP(%esp)
35080Sstevel@tonic-gate#if !defined(__GNUC_AS__)
35090Sstevel@tonic-gate	movw	%ss, %edx
35100Sstevel@tonic-gate#else	/* __GNUC_AS__ */
35110Sstevel@tonic-gate	mov	%ss, %edx
35120Sstevel@tonic-gate#endif	/* __GNUC_AS__ */
35130Sstevel@tonic-gate	movl	%edx, REGOFF_SS(%esp)
35140Sstevel@tonic-gate
35150Sstevel@tonic-gate	movl	%esp, %ecx			/ %ecx = &regs
35160Sstevel@tonic-gate	pushl	%eax				/ push on_panic_stack
35170Sstevel@tonic-gate	pushl	%ecx				/ push &regs
35180Sstevel@tonic-gate	movl	12(%ebp), %ecx			/ %ecx = alist
35190Sstevel@tonic-gate	pushl	%ecx				/ push alist
35200Sstevel@tonic-gate	movl	8(%ebp), %ecx			/ %ecx = format
35210Sstevel@tonic-gate	pushl	%ecx				/ push format
35220Sstevel@tonic-gate	call	panicsys			/ panicsys();
35230Sstevel@tonic-gate	addl	$16, %esp			/ pop arguments
35240Sstevel@tonic-gate
35250Sstevel@tonic-gate	addl	$REGSIZE, %esp
35260Sstevel@tonic-gate	popl	%edx
35270Sstevel@tonic-gate	popl	%ecx
35280Sstevel@tonic-gate	popl	%ebx
35290Sstevel@tonic-gate	popl	%eax
35300Sstevel@tonic-gate	leave
35310Sstevel@tonic-gate	ret
35320Sstevel@tonic-gate	SET_SIZE(vpanic)
35330Sstevel@tonic-gate
35340Sstevel@tonic-gate	ENTRY_NP(dtrace_vpanic)			/ Initial stack layout:
35350Sstevel@tonic-gate
35360Sstevel@tonic-gate	pushl	%ebp				/ | %eip | 20
35370Sstevel@tonic-gate	movl	%esp, %ebp			/ | %ebp | 16
35380Sstevel@tonic-gate	pushl	%eax				/ | %eax | 12
35390Sstevel@tonic-gate	pushl	%ebx				/ | %ebx |  8
35400Sstevel@tonic-gate	pushl	%ecx				/ | %ecx |  4
35410Sstevel@tonic-gate	pushl	%edx				/ | %edx |  0
35420Sstevel@tonic-gate
35430Sstevel@tonic-gate	movl	%esp, %ebx			/ %ebx = current stack pointer
35440Sstevel@tonic-gate
35450Sstevel@tonic-gate	lea	panic_quiesce, %eax		/ %eax = &panic_quiesce
35460Sstevel@tonic-gate	pushl	%eax				/ push &panic_quiesce
35470Sstevel@tonic-gate	call	dtrace_panic_trigger		/ %eax = dtrace_panic_trigger()
35480Sstevel@tonic-gate	addl	$4, %esp			/ reset stack pointer
35490Sstevel@tonic-gate	jmp	vpanic_common			/ jump back to common code
35500Sstevel@tonic-gate
35510Sstevel@tonic-gate	SET_SIZE(dtrace_vpanic)
35520Sstevel@tonic-gate
35530Sstevel@tonic-gate#endif	/* __i386 */
35540Sstevel@tonic-gate#endif	/* __lint */
35550Sstevel@tonic-gate
35560Sstevel@tonic-gate#if defined(__lint)
35570Sstevel@tonic-gate
35580Sstevel@tonic-gatevoid
35590Sstevel@tonic-gatehres_tick(void)
35600Sstevel@tonic-gate{}
35610Sstevel@tonic-gate
35620Sstevel@tonic-gateint64_t timedelta;
35630Sstevel@tonic-gatehrtime_t hres_last_tick;
35644551Ssudheervolatile timestruc_t hrestime;
35650Sstevel@tonic-gateint64_t hrestime_adj;
35660Sstevel@tonic-gatevolatile int hres_lock;
35670Sstevel@tonic-gatehrtime_t hrtime_base;
35680Sstevel@tonic-gate
35690Sstevel@tonic-gate#else	/* __lint */
35700Sstevel@tonic-gate
35710Sstevel@tonic-gate	DGDEF3(hrestime, _MUL(2, CLONGSIZE), 8)
35720Sstevel@tonic-gate	.NWORD	0, 0
35730Sstevel@tonic-gate
35740Sstevel@tonic-gate	DGDEF3(hrestime_adj, 8, 8)
35750Sstevel@tonic-gate	.long	0, 0
35760Sstevel@tonic-gate
35770Sstevel@tonic-gate	DGDEF3(hres_last_tick, 8, 8)
35780Sstevel@tonic-gate	.long	0, 0
35790Sstevel@tonic-gate
35800Sstevel@tonic-gate	DGDEF3(timedelta, 8, 8)
35810Sstevel@tonic-gate	.long	0, 0
35820Sstevel@tonic-gate
35830Sstevel@tonic-gate	DGDEF3(hres_lock, 4, 8)
35840Sstevel@tonic-gate	.long	0
35850Sstevel@tonic-gate
35860Sstevel@tonic-gate	/*
35870Sstevel@tonic-gate	 * initialized to a non zero value to make pc_gethrtime()
35880Sstevel@tonic-gate	 * work correctly even before clock is initialized
35890Sstevel@tonic-gate	 */
35900Sstevel@tonic-gate	DGDEF3(hrtime_base, 8, 8)
35910Sstevel@tonic-gate	.long	_MUL(NSEC_PER_CLOCK_TICK, 6), 0
35920Sstevel@tonic-gate
35930Sstevel@tonic-gate	DGDEF3(adj_shift, 4, 4)
35940Sstevel@tonic-gate	.long	ADJ_SHIFT
35950Sstevel@tonic-gate
35960Sstevel@tonic-gate#if defined(__amd64)
35970Sstevel@tonic-gate
35980Sstevel@tonic-gate	ENTRY_NP(hres_tick)
35990Sstevel@tonic-gate	pushq	%rbp
36000Sstevel@tonic-gate	movq	%rsp, %rbp
36010Sstevel@tonic-gate
36020Sstevel@tonic-gate	/*
36030Sstevel@tonic-gate	 * We need to call *gethrtimef before picking up CLOCK_LOCK (obviously,
36040Sstevel@tonic-gate	 * hres_last_tick can only be modified while holding CLOCK_LOCK).
36050Sstevel@tonic-gate	 * At worst, performing this now instead of under CLOCK_LOCK may
36060Sstevel@tonic-gate	 * introduce some jitter in pc_gethrestime().
36070Sstevel@tonic-gate	 */
36080Sstevel@tonic-gate	call	*gethrtimef(%rip)
36090Sstevel@tonic-gate	movq	%rax, %r8
36100Sstevel@tonic-gate
36110Sstevel@tonic-gate	leaq	hres_lock(%rip), %rax
36120Sstevel@tonic-gate	movb	$-1, %dl
36130Sstevel@tonic-gate.CL1:
36140Sstevel@tonic-gate	xchgb	%dl, (%rax)
36150Sstevel@tonic-gate	testb	%dl, %dl
36160Sstevel@tonic-gate	jz	.CL3			/* got it */
36170Sstevel@tonic-gate.CL2:
36180Sstevel@tonic-gate	cmpb	$0, (%rax)		/* possible to get lock? */
36190Sstevel@tonic-gate	pause
36200Sstevel@tonic-gate	jne	.CL2
36210Sstevel@tonic-gate	jmp	.CL1			/* yes, try again */
36220Sstevel@tonic-gate.CL3:
36230Sstevel@tonic-gate	/*
36240Sstevel@tonic-gate	 * compute the interval since last time hres_tick was called
36250Sstevel@tonic-gate	 * and adjust hrtime_base and hrestime accordingly
36260Sstevel@tonic-gate	 * hrtime_base is an 8 byte value (in nsec), hrestime is
36270Sstevel@tonic-gate	 * a timestruc_t (sec, nsec)
36280Sstevel@tonic-gate	 */
36290Sstevel@tonic-gate	leaq	hres_last_tick(%rip), %rax
36300Sstevel@tonic-gate	movq	%r8, %r11
36310Sstevel@tonic-gate	subq	(%rax), %r8
36320Sstevel@tonic-gate	addq	%r8, hrtime_base(%rip)	/* add interval to hrtime_base */
36330Sstevel@tonic-gate	addq	%r8, hrestime+8(%rip)	/* add interval to hrestime.tv_nsec */
36340Sstevel@tonic-gate	/*
36350Sstevel@tonic-gate	 * Now that we have CLOCK_LOCK, we can update hres_last_tick
36360Sstevel@tonic-gate	 */
36370Sstevel@tonic-gate	movq	%r11, (%rax)
36380Sstevel@tonic-gate
36390Sstevel@tonic-gate	call	__adj_hrestime
36400Sstevel@tonic-gate
36410Sstevel@tonic-gate	/*
36420Sstevel@tonic-gate	 * release the hres_lock
36430Sstevel@tonic-gate	 */
36440Sstevel@tonic-gate	incl	hres_lock(%rip)
36450Sstevel@tonic-gate	leave
36460Sstevel@tonic-gate	ret
36470Sstevel@tonic-gate	SET_SIZE(hres_tick)
36480Sstevel@tonic-gate
36490Sstevel@tonic-gate#elif defined(__i386)
36500Sstevel@tonic-gate
36510Sstevel@tonic-gate	ENTRY_NP(hres_tick)
36520Sstevel@tonic-gate	pushl	%ebp
36530Sstevel@tonic-gate	movl	%esp, %ebp
36540Sstevel@tonic-gate	pushl	%esi
36550Sstevel@tonic-gate	pushl	%ebx
36560Sstevel@tonic-gate
36570Sstevel@tonic-gate	/*
36580Sstevel@tonic-gate	 * We need to call *gethrtimef before picking up CLOCK_LOCK (obviously,
36590Sstevel@tonic-gate	 * hres_last_tick can only be modified while holding CLOCK_LOCK).
36600Sstevel@tonic-gate	 * At worst, performing this now instead of under CLOCK_LOCK may
36610Sstevel@tonic-gate	 * introduce some jitter in pc_gethrestime().
36620Sstevel@tonic-gate	 */
36630Sstevel@tonic-gate	call	*gethrtimef
36640Sstevel@tonic-gate	movl	%eax, %ebx
36650Sstevel@tonic-gate	movl	%edx, %esi
36660Sstevel@tonic-gate
36670Sstevel@tonic-gate	movl	$hres_lock, %eax
36680Sstevel@tonic-gate	movl	$-1, %edx
36690Sstevel@tonic-gate.CL1:
36700Sstevel@tonic-gate	xchgb	%dl, (%eax)
36710Sstevel@tonic-gate	testb	%dl, %dl
36720Sstevel@tonic-gate	jz	.CL3			/ got it
36730Sstevel@tonic-gate.CL2:
36740Sstevel@tonic-gate	cmpb	$0, (%eax)		/ possible to get lock?
36750Sstevel@tonic-gate	pause
36760Sstevel@tonic-gate	jne	.CL2
36770Sstevel@tonic-gate	jmp	.CL1			/ yes, try again
36780Sstevel@tonic-gate.CL3:
36790Sstevel@tonic-gate	/*
36800Sstevel@tonic-gate	 * compute the interval since last time hres_tick was called
36810Sstevel@tonic-gate	 * and adjust hrtime_base and hrestime accordingly
36820Sstevel@tonic-gate	 * hrtime_base is an 8 byte value (in nsec), hrestime is
36830Sstevel@tonic-gate	 * timestruc_t (sec, nsec)
36840Sstevel@tonic-gate	 */
36850Sstevel@tonic-gate
36860Sstevel@tonic-gate	lea	hres_last_tick, %eax
36870Sstevel@tonic-gate
36880Sstevel@tonic-gate	movl	%ebx, %edx
36890Sstevel@tonic-gate	movl	%esi, %ecx
36900Sstevel@tonic-gate
36910Sstevel@tonic-gate	subl 	(%eax), %edx
36920Sstevel@tonic-gate	sbbl 	4(%eax), %ecx
36930Sstevel@tonic-gate
36940Sstevel@tonic-gate	addl	%edx, hrtime_base	/ add interval to hrtime_base
36950Sstevel@tonic-gate	adcl	%ecx, hrtime_base+4
36960Sstevel@tonic-gate
36970Sstevel@tonic-gate	addl 	%edx, hrestime+4	/ add interval to hrestime.tv_nsec
36980Sstevel@tonic-gate
36990Sstevel@tonic-gate	/
37000Sstevel@tonic-gate	/ Now that we have CLOCK_LOCK, we can update hres_last_tick.
37010Sstevel@tonic-gate	/
37020Sstevel@tonic-gate	movl	%ebx, (%eax)
37030Sstevel@tonic-gate	movl	%esi,  4(%eax)
37040Sstevel@tonic-gate
37050Sstevel@tonic-gate	/ get hrestime at this moment. used as base for pc_gethrestime
37060Sstevel@tonic-gate	/
37070Sstevel@tonic-gate	/ Apply adjustment, if any
37080Sstevel@tonic-gate	/
37090Sstevel@tonic-gate	/ #define HRES_ADJ	(NSEC_PER_CLOCK_TICK >> ADJ_SHIFT)
37100Sstevel@tonic-gate	/ (max_hres_adj)
37110Sstevel@tonic-gate	/
37120Sstevel@tonic-gate	/ void
37130Sstevel@tonic-gate	/ adj_hrestime()
37140Sstevel@tonic-gate	/ {
37150Sstevel@tonic-gate	/	long long adj;
37160Sstevel@tonic-gate	/
37170Sstevel@tonic-gate	/	if (hrestime_adj == 0)
37180Sstevel@tonic-gate	/		adj = 0;
37190Sstevel@tonic-gate	/	else if (hrestime_adj > 0) {
37200Sstevel@tonic-gate	/		if (hrestime_adj < HRES_ADJ)
37210Sstevel@tonic-gate	/			adj = hrestime_adj;
37220Sstevel@tonic-gate	/		else
37230Sstevel@tonic-gate	/			adj = HRES_ADJ;
37240Sstevel@tonic-gate	/	}
37250Sstevel@tonic-gate	/	else {
37260Sstevel@tonic-gate	/		if (hrestime_adj < -(HRES_ADJ))
37270Sstevel@tonic-gate	/			adj = -(HRES_ADJ);
37280Sstevel@tonic-gate	/		else
37290Sstevel@tonic-gate	/			adj = hrestime_adj;
37300Sstevel@tonic-gate	/	}
37310Sstevel@tonic-gate	/
37320Sstevel@tonic-gate	/	timedelta -= adj;
37330Sstevel@tonic-gate	/	hrestime_adj = timedelta;
37340Sstevel@tonic-gate	/	hrestime.tv_nsec += adj;
37350Sstevel@tonic-gate	/
37360Sstevel@tonic-gate	/	while (hrestime.tv_nsec >= NANOSEC) {
37370Sstevel@tonic-gate	/		one_sec++;
37380Sstevel@tonic-gate	/		hrestime.tv_sec++;
37390Sstevel@tonic-gate	/		hrestime.tv_nsec -= NANOSEC;
37400Sstevel@tonic-gate	/	}
37410Sstevel@tonic-gate	/ }
37420Sstevel@tonic-gate__adj_hrestime:
37430Sstevel@tonic-gate	movl	hrestime_adj, %esi	/ if (hrestime_adj == 0)
37440Sstevel@tonic-gate	movl	hrestime_adj+4, %edx
37450Sstevel@tonic-gate	andl	%esi, %esi
37460Sstevel@tonic-gate	jne	.CL4			/ no
37470Sstevel@tonic-gate	andl	%edx, %edx
37480Sstevel@tonic-gate	jne	.CL4			/ no
37490Sstevel@tonic-gate	subl	%ecx, %ecx		/ yes, adj = 0;
37500Sstevel@tonic-gate	subl	%edx, %edx
37510Sstevel@tonic-gate	jmp	.CL5
37520Sstevel@tonic-gate.CL4:
37530Sstevel@tonic-gate	subl	%ecx, %ecx
37540Sstevel@tonic-gate	subl	%eax, %eax
37550Sstevel@tonic-gate	subl	%esi, %ecx
37560Sstevel@tonic-gate	sbbl	%edx, %eax
37570Sstevel@tonic-gate	andl	%eax, %eax		/ if (hrestime_adj > 0)
37580Sstevel@tonic-gate	jge	.CL6
37590Sstevel@tonic-gate
37600Sstevel@tonic-gate	/ In the following comments, HRES_ADJ is used, while in the code
37610Sstevel@tonic-gate	/ max_hres_adj is used.
37620Sstevel@tonic-gate	/
37630Sstevel@tonic-gate	/ The test for "hrestime_adj < HRES_ADJ" is complicated because
37640Sstevel@tonic-gate	/ hrestime_adj is 64-bits, while HRES_ADJ is 32-bits.  We rely
37650Sstevel@tonic-gate	/ on the logical equivalence of:
37660Sstevel@tonic-gate	/
37670Sstevel@tonic-gate	/	!(hrestime_adj < HRES_ADJ)
37680Sstevel@tonic-gate	/
37690Sstevel@tonic-gate	/ and the two step sequence:
37700Sstevel@tonic-gate	/
37710Sstevel@tonic-gate	/	(HRES_ADJ - lsw(hrestime_adj)) generates a Borrow/Carry
37720Sstevel@tonic-gate	/
37730Sstevel@tonic-gate	/ which computes whether or not the least significant 32-bits
37740Sstevel@tonic-gate	/ of hrestime_adj is greater than HRES_ADJ, followed by:
37750Sstevel@tonic-gate	/
37760Sstevel@tonic-gate	/	Previous Borrow/Carry + -1 + msw(hrestime_adj) generates a Carry
37770Sstevel@tonic-gate	/
37780Sstevel@tonic-gate	/ which generates a carry whenever step 1 is true or the most
37790Sstevel@tonic-gate	/ significant long of the longlong hrestime_adj is non-zero.
37800Sstevel@tonic-gate
37810Sstevel@tonic-gate	movl	max_hres_adj, %ecx	/ hrestime_adj is positive
37820Sstevel@tonic-gate	subl	%esi, %ecx
37830Sstevel@tonic-gate	movl	%edx, %eax
37840Sstevel@tonic-gate	adcl	$-1, %eax
37850Sstevel@tonic-gate	jnc	.CL7
37860Sstevel@tonic-gate	movl	max_hres_adj, %ecx	/ adj = HRES_ADJ;
37870Sstevel@tonic-gate	subl	%edx, %edx
37880Sstevel@tonic-gate	jmp	.CL5
37890Sstevel@tonic-gate
37900Sstevel@tonic-gate	/ The following computation is similar to the one above.
37910Sstevel@tonic-gate	/
37920Sstevel@tonic-gate	/ The test for "hrestime_adj < -(HRES_ADJ)" is complicated because
37930Sstevel@tonic-gate	/ hrestime_adj is 64-bits, while HRES_ADJ is 32-bits.  We rely
37940Sstevel@tonic-gate	/ on the logical equivalence of:
37950Sstevel@tonic-gate	/
37960Sstevel@tonic-gate	/	(hrestime_adj > -HRES_ADJ)
37970Sstevel@tonic-gate	/
37980Sstevel@tonic-gate	/ and the two step sequence:
37990Sstevel@tonic-gate	/
38000Sstevel@tonic-gate	/	(HRES_ADJ + lsw(hrestime_adj)) generates a Carry
38010Sstevel@tonic-gate	/
38020Sstevel@tonic-gate	/ which means the least significant 32-bits of hrestime_adj is
38030Sstevel@tonic-gate	/ greater than -HRES_ADJ, followed by:
38040Sstevel@tonic-gate	/
38050Sstevel@tonic-gate	/	Previous Carry + 0 + msw(hrestime_adj) generates a Carry
38060Sstevel@tonic-gate	/
38070Sstevel@tonic-gate	/ which generates a carry only when step 1 is true and the most
38080Sstevel@tonic-gate	/ significant long of the longlong hrestime_adj is -1.
38090Sstevel@tonic-gate
38100Sstevel@tonic-gate.CL6:					/ hrestime_adj is negative
38110Sstevel@tonic-gate	movl	%esi, %ecx
38120Sstevel@tonic-gate	addl	max_hres_adj, %ecx
38130Sstevel@tonic-gate	movl	%edx, %eax
38140Sstevel@tonic-gate	adcl	$0, %eax
38150Sstevel@tonic-gate	jc	.CL7
38160Sstevel@tonic-gate	xor	%ecx, %ecx
38170Sstevel@tonic-gate	subl	max_hres_adj, %ecx	/ adj = -(HRES_ADJ);
38180Sstevel@tonic-gate	movl	$-1, %edx
38190Sstevel@tonic-gate	jmp	.CL5
38200Sstevel@tonic-gate.CL7:
38210Sstevel@tonic-gate	movl	%esi, %ecx		/ adj = hrestime_adj;
38220Sstevel@tonic-gate.CL5:
38230Sstevel@tonic-gate	movl	timedelta, %esi
38240Sstevel@tonic-gate	subl	%ecx, %esi
38250Sstevel@tonic-gate	movl	timedelta+4, %eax
38260Sstevel@tonic-gate	sbbl	%edx, %eax
38270Sstevel@tonic-gate	movl	%esi, timedelta
38280Sstevel@tonic-gate	movl	%eax, timedelta+4	/ timedelta -= adj;
38290Sstevel@tonic-gate	movl	%esi, hrestime_adj
38300Sstevel@tonic-gate	movl	%eax, hrestime_adj+4	/ hrestime_adj = timedelta;
38310Sstevel@tonic-gate	addl	hrestime+4, %ecx
38320Sstevel@tonic-gate
38330Sstevel@tonic-gate	movl	%ecx, %eax		/ eax = tv_nsec
38340Sstevel@tonic-gate1:
38350Sstevel@tonic-gate	cmpl	$NANOSEC, %eax		/ if ((unsigned long)tv_nsec >= NANOSEC)
38360Sstevel@tonic-gate	jb	.CL8			/ no
38370Sstevel@tonic-gate	incl	one_sec			/ yes,  one_sec++;
38380Sstevel@tonic-gate	incl	hrestime		/ hrestime.tv_sec++;
38390Sstevel@tonic-gate	addl	$-NANOSEC, %eax		/ tv_nsec -= NANOSEC
38400Sstevel@tonic-gate	jmp	1b			/ check for more seconds
38410Sstevel@tonic-gate
38420Sstevel@tonic-gate.CL8:
38430Sstevel@tonic-gate	movl	%eax, hrestime+4	/ store final into hrestime.tv_nsec
38440Sstevel@tonic-gate	incl	hres_lock		/ release the hres_lock
38450Sstevel@tonic-gate
38460Sstevel@tonic-gate	popl	%ebx
38470Sstevel@tonic-gate	popl	%esi
38480Sstevel@tonic-gate	leave
38490Sstevel@tonic-gate	ret
38500Sstevel@tonic-gate	SET_SIZE(hres_tick)
38510Sstevel@tonic-gate
38520Sstevel@tonic-gate#endif	/* __i386 */
38530Sstevel@tonic-gate#endif	/* __lint */
38540Sstevel@tonic-gate
38550Sstevel@tonic-gate/*
38560Sstevel@tonic-gate * void prefetch_smap_w(void *)
38570Sstevel@tonic-gate *
38580Sstevel@tonic-gate * Prefetch ahead within a linear list of smap structures.
38590Sstevel@tonic-gate * Not implemented for ia32.  Stub for compatibility.
38600Sstevel@tonic-gate */
38610Sstevel@tonic-gate
38620Sstevel@tonic-gate#if defined(__lint)
38630Sstevel@tonic-gate
38640Sstevel@tonic-gate/*ARGSUSED*/
38650Sstevel@tonic-gatevoid prefetch_smap_w(void *smp)
38660Sstevel@tonic-gate{}
38670Sstevel@tonic-gate
38680Sstevel@tonic-gate#else	/* __lint */
38690Sstevel@tonic-gate
38700Sstevel@tonic-gate	ENTRY(prefetch_smap_w)
3871545Skalai	rep;	ret	/* use 2 byte return instruction when branch target */
3872545Skalai			/* AMD Software Optimization Guide - Section 6.2 */
38730Sstevel@tonic-gate	SET_SIZE(prefetch_smap_w)
38740Sstevel@tonic-gate
38750Sstevel@tonic-gate#endif	/* __lint */
38760Sstevel@tonic-gate
38770Sstevel@tonic-gate/*
38780Sstevel@tonic-gate * prefetch_page_r(page_t *)
38790Sstevel@tonic-gate * issue prefetch instructions for a page_t
38800Sstevel@tonic-gate */
38810Sstevel@tonic-gate#if defined(__lint)
38820Sstevel@tonic-gate
38830Sstevel@tonic-gate/*ARGSUSED*/
38840Sstevel@tonic-gatevoid
38850Sstevel@tonic-gateprefetch_page_r(void *pp)
38860Sstevel@tonic-gate{}
38870Sstevel@tonic-gate
38880Sstevel@tonic-gate#else	/* __lint */
38890Sstevel@tonic-gate
38900Sstevel@tonic-gate	ENTRY(prefetch_page_r)
3891545Skalai	rep;	ret	/* use 2 byte return instruction when branch target */
3892545Skalai			/* AMD Software Optimization Guide - Section 6.2 */
38930Sstevel@tonic-gate	SET_SIZE(prefetch_page_r)
38940Sstevel@tonic-gate
38950Sstevel@tonic-gate#endif	/* __lint */
38960Sstevel@tonic-gate
38970Sstevel@tonic-gate#if defined(__lint)
38980Sstevel@tonic-gate
38990Sstevel@tonic-gate/*ARGSUSED*/
39000Sstevel@tonic-gateint
39010Sstevel@tonic-gatebcmp(const void *s1, const void *s2, size_t count)
39020Sstevel@tonic-gate{ return (0); }
39030Sstevel@tonic-gate
39040Sstevel@tonic-gate#else   /* __lint */
39050Sstevel@tonic-gate
39060Sstevel@tonic-gate#if defined(__amd64)
39070Sstevel@tonic-gate
39080Sstevel@tonic-gate	ENTRY(bcmp)
39090Sstevel@tonic-gate	pushq	%rbp
39100Sstevel@tonic-gate	movq	%rsp, %rbp
39110Sstevel@tonic-gate#ifdef DEBUG
39123446Smrj	movq	postbootkernelbase(%rip), %r11
39130Sstevel@tonic-gate	cmpq	%r11, %rdi
39140Sstevel@tonic-gate	jb	0f
39150Sstevel@tonic-gate	cmpq	%r11, %rsi
39160Sstevel@tonic-gate	jnb	1f
39170Sstevel@tonic-gate0:	leaq	.bcmp_panic_msg(%rip), %rdi
39180Sstevel@tonic-gate	xorl	%eax, %eax
39190Sstevel@tonic-gate	call	panic
39200Sstevel@tonic-gate1:
39210Sstevel@tonic-gate#endif	/* DEBUG */
39220Sstevel@tonic-gate	call	memcmp
39230Sstevel@tonic-gate	testl	%eax, %eax
39240Sstevel@tonic-gate	setne	%dl
39250Sstevel@tonic-gate	leave
39260Sstevel@tonic-gate	movzbl	%dl, %eax
39270Sstevel@tonic-gate	ret
39280Sstevel@tonic-gate	SET_SIZE(bcmp)
39290Sstevel@tonic-gate
39300Sstevel@tonic-gate#elif defined(__i386)
39310Sstevel@tonic-gate
39320Sstevel@tonic-gate#define	ARG_S1		8
39330Sstevel@tonic-gate#define	ARG_S2		12
39340Sstevel@tonic-gate#define	ARG_LENGTH	16
39350Sstevel@tonic-gate
39360Sstevel@tonic-gate	ENTRY(bcmp)
39373412Sjj204856	pushl	%ebp
39383412Sjj204856	movl	%esp, %ebp	/ create new stack frame
39390Sstevel@tonic-gate#ifdef DEBUG
39403446Smrj	movl    postbootkernelbase, %eax
39410Sstevel@tonic-gate	cmpl    %eax, ARG_S1(%ebp)
39420Sstevel@tonic-gate	jb	0f
39430Sstevel@tonic-gate	cmpl    %eax, ARG_S2(%ebp)
39440Sstevel@tonic-gate	jnb	1f
39450Sstevel@tonic-gate0:	pushl   $.bcmp_panic_msg
39460Sstevel@tonic-gate	call    panic
39473412Sjj2048561:
39480Sstevel@tonic-gate#endif	/* DEBUG */
39490Sstevel@tonic-gate
39500Sstevel@tonic-gate	pushl	%edi		/ save register variable
39513412Sjj204856	movl	ARG_S1(%ebp), %eax	/ %eax = address of string 1
39523412Sjj204856	movl	ARG_S2(%ebp), %ecx	/ %ecx = address of string 2
39530Sstevel@tonic-gate	cmpl	%eax, %ecx	/ if the same string
39540Sstevel@tonic-gate	je	.equal		/ goto .equal
39553412Sjj204856	movl	ARG_LENGTH(%ebp), %edi	/ %edi = length in bytes
39560Sstevel@tonic-gate	cmpl	$4, %edi	/ if %edi < 4
39570Sstevel@tonic-gate	jb	.byte_check	/ goto .byte_check
39580Sstevel@tonic-gate	.align	4
39590Sstevel@tonic-gate.word_loop:
39600Sstevel@tonic-gate	movl	(%ecx), %edx	/ move 1 word from (%ecx) to %edx
39610Sstevel@tonic-gate	leal	-4(%edi), %edi	/ %edi -= 4
39620Sstevel@tonic-gate	cmpl	(%eax), %edx	/ compare 1 word from (%eax) with %edx
39630Sstevel@tonic-gate	jne	.word_not_equal	/ if not equal, goto .word_not_equal
39640Sstevel@tonic-gate	leal	4(%ecx), %ecx	/ %ecx += 4 (next word)
39650Sstevel@tonic-gate	leal	4(%eax), %eax	/ %eax += 4 (next word)
39660Sstevel@tonic-gate	cmpl	$4, %edi	/ if %edi >= 4
39670Sstevel@tonic-gate	jae	.word_loop	/ goto .word_loop
39680Sstevel@tonic-gate.byte_check:
39690Sstevel@tonic-gate	cmpl	$0, %edi	/ if %edi == 0
39700Sstevel@tonic-gate	je	.equal		/ goto .equal
39710Sstevel@tonic-gate	jmp	.byte_loop	/ goto .byte_loop (checks in bytes)
39720Sstevel@tonic-gate.word_not_equal:
39730Sstevel@tonic-gate	leal	4(%edi), %edi	/ %edi += 4 (post-decremented)
39740Sstevel@tonic-gate	.align	4
39750Sstevel@tonic-gate.byte_loop:
39760Sstevel@tonic-gate	movb	(%ecx),	%dl	/ move 1 byte from (%ecx) to %dl
39770Sstevel@tonic-gate	cmpb	%dl, (%eax)	/ compare %dl with 1 byte from (%eax)
39780Sstevel@tonic-gate	jne	.not_equal	/ if not equal, goto .not_equal
39790Sstevel@tonic-gate	incl	%ecx		/ %ecx++ (next byte)
39800Sstevel@tonic-gate	incl	%eax		/ %eax++ (next byte)
39810Sstevel@tonic-gate	decl	%edi		/ %edi--
39820Sstevel@tonic-gate	jnz	.byte_loop	/ if not zero, goto .byte_loop
39830Sstevel@tonic-gate.equal:
39840Sstevel@tonic-gate	xorl	%eax, %eax	/ %eax = 0
39850Sstevel@tonic-gate	popl	%edi		/ restore register variable
39863412Sjj204856	leave			/ restore old stack frame
39870Sstevel@tonic-gate	ret			/ return (NULL)
39880Sstevel@tonic-gate	.align	4
39890Sstevel@tonic-gate.not_equal:
39900Sstevel@tonic-gate	movl	$1, %eax	/ return 1
39910Sstevel@tonic-gate	popl	%edi		/ restore register variable
39923412Sjj204856	leave			/ restore old stack frame
39930Sstevel@tonic-gate	ret			/ return (NULL)
39940Sstevel@tonic-gate	SET_SIZE(bcmp)
39950Sstevel@tonic-gate
39960Sstevel@tonic-gate#endif	/* __i386 */
39970Sstevel@tonic-gate
39980Sstevel@tonic-gate#ifdef DEBUG
39990Sstevel@tonic-gate	.text
40000Sstevel@tonic-gate.bcmp_panic_msg:
40010Sstevel@tonic-gate	.string "bcmp: arguments below kernelbase"
40020Sstevel@tonic-gate#endif	/* DEBUG */
40030Sstevel@tonic-gate
40040Sstevel@tonic-gate#endif	/* __lint */
40053446Smrj
40063446Smrj#if defined(__lint)
40073446Smrj
40083446Smrjuint_t
40093446Smrjbsrw_insn(uint16_t mask)
40103446Smrj{
40113446Smrj	uint_t index = sizeof (mask) * NBBY - 1;
40123446Smrj
40133446Smrj	while ((mask & (1 << index)) == 0)
40143446Smrj		index--;
40153446Smrj	return (index);
40163446Smrj}
40173446Smrj
40183446Smrj#else	/* __lint */
40193446Smrj
40203446Smrj#if defined(__amd64)
40213446Smrj
40223446Smrj	ENTRY_NP(bsrw_insn)
40233446Smrj	xorl	%eax, %eax
40243446Smrj	bsrw	%di, %ax
40253446Smrj	ret
40263446Smrj	SET_SIZE(bsrw_insn)
40273446Smrj
40283446Smrj#elif defined(__i386)
40293446Smrj
40303446Smrj	ENTRY_NP(bsrw_insn)
40313446Smrj	movw	4(%esp), %cx
40323446Smrj	xorl	%eax, %eax
40333446Smrj	bsrw	%cx, %ax
40343446Smrj	ret
40353446Smrj	SET_SIZE(bsrw_insn)
40363446Smrj
40373446Smrj#endif	/* __i386 */
40383446Smrj#endif	/* __lint */
40393446Smrj
40403446Smrj#if defined(__lint)
40413446Smrj
40423446Smrjuint_t
40433446Smrjatomic_btr32(uint32_t *pending, uint_t pil)
40443446Smrj{
40453446Smrj	return (*pending &= ~(1 << pil));
40463446Smrj}
40473446Smrj
40483446Smrj#else	/* __lint */
40493446Smrj
40503446Smrj#if defined(__i386)
40513446Smrj
40523446Smrj	ENTRY_NP(atomic_btr32)
40533446Smrj	movl	4(%esp), %ecx
40543446Smrj	movl	8(%esp), %edx
40553446Smrj	xorl	%eax, %eax
40563446Smrj	lock
40573446Smrj	btrl	%edx, (%ecx)
40583446Smrj	setc	%al
40593446Smrj	ret
40603446Smrj	SET_SIZE(atomic_btr32)
40613446Smrj
40623446Smrj#endif	/* __i386 */
40633446Smrj#endif	/* __lint */
40643446Smrj
40653446Smrj#if defined(__lint)
40663446Smrj
40673446Smrj/*ARGSUSED*/
40683446Smrjvoid
40693446Smrjswitch_sp_and_call(void *newsp, void (*func)(uint_t, uint_t), uint_t arg1,
40703446Smrj	    uint_t arg2)
40713446Smrj{}
40723446Smrj
40733446Smrj#else	/* __lint */
40743446Smrj
40753446Smrj#if defined(__amd64)
40763446Smrj
40773446Smrj	ENTRY_NP(switch_sp_and_call)
40783446Smrj	pushq	%rbp
40793446Smrj	movq	%rsp, %rbp		/* set up stack frame */
40803446Smrj	movq	%rdi, %rsp		/* switch stack pointer */
40813446Smrj	movq	%rdx, %rdi		/* pass func arg 1 */
40823446Smrj	movq	%rsi, %r11		/* save function to call */
40833446Smrj	movq	%rcx, %rsi		/* pass func arg 2 */
40843446Smrj	call	*%r11			/* call function */
40853446Smrj	leave				/* restore stack */
40863446Smrj	ret
40873446Smrj	SET_SIZE(switch_sp_and_call)
40883446Smrj
40893446Smrj#elif defined(__i386)
40903446Smrj
40913446Smrj	ENTRY_NP(switch_sp_and_call)
40923446Smrj	pushl	%ebp
40933446Smrj	mov	%esp, %ebp		/* set up stack frame */
40943446Smrj	movl	8(%ebp), %esp		/* switch stack pointer */
40953446Smrj	pushl	20(%ebp)		/* push func arg 2 */
40963446Smrj	pushl	16(%ebp)		/* push func arg 1 */
40973446Smrj	call	*12(%ebp)		/* call function */
40983446Smrj	addl	$8, %esp		/* pop arguments */
40993446Smrj	leave				/* restore stack */
41003446Smrj	ret
41013446Smrj	SET_SIZE(switch_sp_and_call)
41023446Smrj
41033446Smrj#endif	/* __i386 */
41043446Smrj#endif	/* __lint */
41053446Smrj
41063446Smrj#if defined(__lint)
41073446Smrj
41083446Smrjvoid
41093446Smrjkmdb_enter(void)
41103446Smrj{}
41113446Smrj
41123446Smrj#else	/* __lint */
41133446Smrj
41143446Smrj#if defined(__amd64)
41153446Smrj
41163446Smrj	ENTRY_NP(kmdb_enter)
41173446Smrj	pushq	%rbp
41183446Smrj	movq	%rsp, %rbp
41193446Smrj
41203446Smrj	/*
41213446Smrj	 * Save flags, do a 'cli' then return the saved flags
41223446Smrj	 */
41233446Smrj	call	intr_clear
41243446Smrj
41253446Smrj	int	$T_DBGENTR
41263446Smrj
41273446Smrj	/*
41283446Smrj	 * Restore the saved flags
41293446Smrj	 */
41303446Smrj	movq	%rax, %rdi
41313446Smrj	call	intr_restore
41323446Smrj
41333446Smrj	leave
41343446Smrj	ret
41353446Smrj	SET_SIZE(kmdb_enter)
41363446Smrj
41373446Smrj#elif defined(__i386)
41383446Smrj
41393446Smrj	ENTRY_NP(kmdb_enter)
41403446Smrj	pushl	%ebp
41413446Smrj	movl	%esp, %ebp
41423446Smrj
41433446Smrj	/*
41443446Smrj	 * Save flags, do a 'cli' then return the saved flags
41453446Smrj	 */
41463446Smrj	call	intr_clear
41473446Smrj
41483446Smrj	int	$T_DBGENTR
41493446Smrj
41503446Smrj	/*
41513446Smrj	 * Restore the saved flags
41523446Smrj	 */
41533446Smrj	pushl	%eax
41543446Smrj	call	intr_restore
41553446Smrj	addl	$4, %esp
41563446Smrj
41573446Smrj	leave
41583446Smrj	ret
41593446Smrj	SET_SIZE(kmdb_enter)
41603446Smrj
41613446Smrj#endif	/* __i386 */
41623446Smrj#endif	/* __lint */
41633446Smrj
41643446Smrj#if defined(__lint)
41653446Smrj
41663446Smrjvoid
41673446Smrjreturn_instr(void)
41683446Smrj{}
41693446Smrj
41703446Smrj#else	/* __lint */
41713446Smrj
41723446Smrj	ENTRY_NP(return_instr)
41733446Smrj	rep;	ret	/* use 2 byte instruction when branch target */
41743446Smrj			/* AMD Software Optimization Guide - Section 6.2 */
41753446Smrj	SET_SIZE(return_instr)
41763446Smrj
41773446Smrj#endif	/* __lint */
41783446Smrj
41793446Smrj#if defined(__lint)
41803446Smrj
41813446Smrjulong_t
41823446Smrjgetflags(void)
41833446Smrj{
41843446Smrj	return (0);
41853446Smrj}
41863446Smrj
41873446Smrj#else	/* __lint */
41883446Smrj
41893446Smrj#if defined(__amd64)
41903446Smrj
41913446Smrj	ENTRY(getflags)
41923446Smrj	pushfq
41933446Smrj	popq	%rax
41945084Sjohnlev#if defined(__xpv)
41955084Sjohnlev	CURTHREAD(%rdi)
41965084Sjohnlev	KPREEMPT_DISABLE(%rdi)
41975084Sjohnlev	/*
41985084Sjohnlev	 * Synthesize the PS_IE bit from the event mask bit
41995084Sjohnlev	 */
42005084Sjohnlev	CURVCPU(%r11)
42015084Sjohnlev	andq    $_BITNOT(PS_IE), %rax
42025084Sjohnlev	XEN_TEST_UPCALL_MASK(%r11)
42035084Sjohnlev	jnz	1f
42045084Sjohnlev	orq	$PS_IE, %rax
42055084Sjohnlev1:
42065084Sjohnlev	KPREEMPT_ENABLE_NOKP(%rdi)
42075084Sjohnlev#endif
42083446Smrj	ret
42093446Smrj	SET_SIZE(getflags)
42103446Smrj
42113446Smrj#elif defined(__i386)
42123446Smrj
42133446Smrj	ENTRY(getflags)
42143446Smrj	pushfl
42153446Smrj	popl	%eax
42165084Sjohnlev#if defined(__xpv)
42175084Sjohnlev	CURTHREAD(%ecx)
42185084Sjohnlev	KPREEMPT_DISABLE(%ecx)
42195084Sjohnlev	/*
42205084Sjohnlev	 * Synthesize the PS_IE bit from the event mask bit
42215084Sjohnlev	 */
42225084Sjohnlev	CURVCPU(%edx)
42235084Sjohnlev	andl    $_BITNOT(PS_IE), %eax
42245084Sjohnlev	XEN_TEST_UPCALL_MASK(%edx)
42255084Sjohnlev	jnz	1f
42265084Sjohnlev	orl	$PS_IE, %eax
42275084Sjohnlev1:
42285084Sjohnlev	KPREEMPT_ENABLE_NOKP(%ecx)
42295084Sjohnlev#endif
42303446Smrj	ret
42313446Smrj	SET_SIZE(getflags)
42323446Smrj
42333446Smrj#endif	/* __i386 */
42343446Smrj
42353446Smrj#endif	/* __lint */
42363647Sbs21162
42373647Sbs21162#if defined(__lint)
42383647Sbs21162
42393647Sbs21162ftrace_icookie_t
42403647Sbs21162ftrace_interrupt_disable(void)
42413647Sbs21162{ return (0); }
42423647Sbs21162
42433647Sbs21162#else   /* __lint */
42443647Sbs21162
42453647Sbs21162#if defined(__amd64)
42463647Sbs21162
42473647Sbs21162	ENTRY(ftrace_interrupt_disable)
42483647Sbs21162	pushfq
42493647Sbs21162	popq	%rax
42503647Sbs21162	CLI(%rdx)
42513647Sbs21162	ret
42523647Sbs21162	SET_SIZE(ftrace_interrupt_disable)
42533647Sbs21162
42543647Sbs21162#elif defined(__i386)
42553647Sbs21162
42563647Sbs21162	ENTRY(ftrace_interrupt_disable)
42573647Sbs21162	pushfl
42583647Sbs21162	popl	%eax
42593647Sbs21162	CLI(%edx)
42603647Sbs21162	ret
42613647Sbs21162	SET_SIZE(ftrace_interrupt_disable)
42623647Sbs21162
42633647Sbs21162#endif	/* __i386 */
42643647Sbs21162#endif	/* __lint */
42653647Sbs21162
42663647Sbs21162#if defined(__lint)
42673647Sbs21162
42683647Sbs21162/*ARGSUSED*/
42693647Sbs21162void
42703647Sbs21162ftrace_interrupt_enable(ftrace_icookie_t cookie)
42713647Sbs21162{}
42723647Sbs21162
42733647Sbs21162#else	/* __lint */
42743647Sbs21162
42753647Sbs21162#if defined(__amd64)
42763647Sbs21162
42773647Sbs21162	ENTRY(ftrace_interrupt_enable)
42783647Sbs21162	pushq	%rdi
42793647Sbs21162	popfq
42803647Sbs21162	ret
42813647Sbs21162	SET_SIZE(ftrace_interrupt_enable)
42823647Sbs21162
42833647Sbs21162#elif defined(__i386)
42843647Sbs21162
42853647Sbs21162	ENTRY(ftrace_interrupt_enable)
42863647Sbs21162	movl	4(%esp), %eax
42873647Sbs21162	pushl	%eax
42883647Sbs21162	popfl
42893647Sbs21162	ret
42903647Sbs21162	SET_SIZE(ftrace_interrupt_enable)
42913647Sbs21162
42927589SVikram.Hegde@Sun.COM#endif	/* __i386 */
42933647Sbs21162#endif	/* __lint */
42947589SVikram.Hegde@Sun.COM
42957589SVikram.Hegde@Sun.COM#if defined (__lint)
42967589SVikram.Hegde@Sun.COM
42977589SVikram.Hegde@Sun.COM/*ARGSUSED*/
42987589SVikram.Hegde@Sun.COMvoid
42997589SVikram.Hegde@Sun.COMclflush_insn(caddr_t addr)
43007589SVikram.Hegde@Sun.COM{}
43017589SVikram.Hegde@Sun.COM
43027589SVikram.Hegde@Sun.COM#else /* __lint */
43037589SVikram.Hegde@Sun.COM
43047589SVikram.Hegde@Sun.COM#if defined (__amd64)
43057589SVikram.Hegde@Sun.COM	ENTRY(clflush_insn)
43067589SVikram.Hegde@Sun.COM	clflush (%rdi)
43077589SVikram.Hegde@Sun.COM	ret
43087589SVikram.Hegde@Sun.COM	SET_SIZE(clflush_insn)
43097589SVikram.Hegde@Sun.COM#elif defined (__i386)
43107589SVikram.Hegde@Sun.COM	ENTRY(clflush_insn)
43117589SVikram.Hegde@Sun.COM	movl	4(%esp), %eax
43127589SVikram.Hegde@Sun.COM	clflush (%eax)
43137589SVikram.Hegde@Sun.COM	ret
43147589SVikram.Hegde@Sun.COM	SET_SIZE(clflush_insn)
43157589SVikram.Hegde@Sun.COM
43167589SVikram.Hegde@Sun.COM#endif /* __i386 */
43177589SVikram.Hegde@Sun.COM#endif /* __lint */
43187589SVikram.Hegde@Sun.COM
43197589SVikram.Hegde@Sun.COM#if defined (__lint)
43207589SVikram.Hegde@Sun.COM/*ARGSUSED*/
43217589SVikram.Hegde@Sun.COMvoid
43227589SVikram.Hegde@Sun.COMmfence_insn(void)
43237589SVikram.Hegde@Sun.COM{}
43247589SVikram.Hegde@Sun.COM
43257589SVikram.Hegde@Sun.COM#else /* __lint */
43267589SVikram.Hegde@Sun.COM
43277589SVikram.Hegde@Sun.COM#if defined (__amd64)
43287589SVikram.Hegde@Sun.COM	ENTRY(mfence_insn)
43297589SVikram.Hegde@Sun.COM	mfence
43307589SVikram.Hegde@Sun.COM	ret
43317589SVikram.Hegde@Sun.COM	SET_SIZE(mfence_insn)
43327589SVikram.Hegde@Sun.COM#elif defined (__i386)
43337589SVikram.Hegde@Sun.COM	ENTRY(mfence_insn)
43347589SVikram.Hegde@Sun.COM	mfence
43357589SVikram.Hegde@Sun.COM	ret
43367589SVikram.Hegde@Sun.COM	SET_SIZE(mfence_insn)
43377589SVikram.Hegde@Sun.COM
43387589SVikram.Hegde@Sun.COM#endif /* __i386 */
43397589SVikram.Hegde@Sun.COM#endif /* __lint */
43408990SSurya.Prakki@Sun.COM
43418990SSurya.Prakki@Sun.COM/*
43428990SSurya.Prakki@Sun.COM * This is how VMware lets the guests figure that they are running
43438990SSurya.Prakki@Sun.COM * on top of VMWare platform :
43448990SSurya.Prakki@Sun.COM * Write 0xA in the ECX register and put the I/O port address value of
43458990SSurya.Prakki@Sun.COM * 0x564D5868 in the EAX register. Then read a word from port 0x5658.
43468990SSurya.Prakki@Sun.COM * If VMWare is installed than this code will be executed correctly and
43478990SSurya.Prakki@Sun.COM * the EBX register will contain the same I/O port address value of 0x564D5868.
43488990SSurya.Prakki@Sun.COM * If VMWare is not installed then OS will return an exception on port access.
43498990SSurya.Prakki@Sun.COM */
43508990SSurya.Prakki@Sun.COM#if defined(__lint)
43518990SSurya.Prakki@Sun.COM
43528990SSurya.Prakki@Sun.COMint
43538990SSurya.Prakki@Sun.COMvmware_platform(void) { return (1); }
43548990SSurya.Prakki@Sun.COM
43558990SSurya.Prakki@Sun.COM#else
43568990SSurya.Prakki@Sun.COM
43578990SSurya.Prakki@Sun.COM#if defined(__amd64)
43588990SSurya.Prakki@Sun.COM
43598990SSurya.Prakki@Sun.COM	ENTRY(vmware_platform)
43608990SSurya.Prakki@Sun.COM	pushq	%rbx
43618990SSurya.Prakki@Sun.COM	xorl	%ebx, %ebx
43628990SSurya.Prakki@Sun.COM	movl	$0x564d5868, %eax
43638990SSurya.Prakki@Sun.COM	movl	$0xa, %ecx
43648990SSurya.Prakki@Sun.COM	movl	$0x5658, %edx
43658990SSurya.Prakki@Sun.COM	inl	(%dx)
43668990SSurya.Prakki@Sun.COM	movl	$0x564d5868, %ecx
43678990SSurya.Prakki@Sun.COM	xorl	%eax, %eax
43688990SSurya.Prakki@Sun.COM	cmpl	%ecx, %ebx
43698990SSurya.Prakki@Sun.COM	jne	1f
43708990SSurya.Prakki@Sun.COM	incl	%eax
43718990SSurya.Prakki@Sun.COM1:
43728990SSurya.Prakki@Sun.COM	popq	%rbx
43738990SSurya.Prakki@Sun.COM	ret
43748990SSurya.Prakki@Sun.COM	SET_SIZE(vmware_platform)
43758990SSurya.Prakki@Sun.COM
43768990SSurya.Prakki@Sun.COM#elif defined(__i386)
43778990SSurya.Prakki@Sun.COM
43788990SSurya.Prakki@Sun.COM	ENTRY(vmware_platform)
43798990SSurya.Prakki@Sun.COM	pushl	%ebx
43808990SSurya.Prakki@Sun.COM	pushl	%ecx
43818990SSurya.Prakki@Sun.COM	pushl	%edx
43828990SSurya.Prakki@Sun.COM	xorl	%ebx, %ebx
43838990SSurya.Prakki@Sun.COM	movl	$0x564d5868, %eax
43848990SSurya.Prakki@Sun.COM	movl	$0xa, %ecx
43858990SSurya.Prakki@Sun.COM	movl	$0x5658, %edx
43868990SSurya.Prakki@Sun.COM	inl	(%dx)
43878990SSurya.Prakki@Sun.COM	movl	$0x564d5868, %ecx
43888990SSurya.Prakki@Sun.COM	xorl	%eax, %eax
43898990SSurya.Prakki@Sun.COM	cmpl	%ecx, %ebx
43908990SSurya.Prakki@Sun.COM	jne	1f
43918990SSurya.Prakki@Sun.COM	incl	%eax
43928990SSurya.Prakki@Sun.COM1:
43938990SSurya.Prakki@Sun.COM	popl	%edx
43948990SSurya.Prakki@Sun.COM	popl	%ecx
43958990SSurya.Prakki@Sun.COM	popl	%ebx
43968990SSurya.Prakki@Sun.COM	ret
43978990SSurya.Prakki@Sun.COM	SET_SIZE(vmware_platform)
43988990SSurya.Prakki@Sun.COM
43998990SSurya.Prakki@Sun.COM#endif /* __i386 */
44008990SSurya.Prakki@Sun.COM#endif /* __lint */
4401