xref: /onnv-gate/usr/src/uts/sun4v/cpu/common_asm.s (revision 12908:80a39220b451)
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
51614Sjb145095 * Common Development and Distribution License (the "License").
61614Sjb145095 * 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 */
210Sstevel@tonic-gate/*
22*12908SPavel.Tatashin@Sun.COM * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate */
240Sstevel@tonic-gate
250Sstevel@tonic-gate#if !defined(lint)
260Sstevel@tonic-gate#include "assym.h"
270Sstevel@tonic-gate#endif
280Sstevel@tonic-gate
290Sstevel@tonic-gate/*
300Sstevel@tonic-gate * General assembly language routines.
310Sstevel@tonic-gate * It is the intent of this file to contain routines that are
320Sstevel@tonic-gate * specific to cpu architecture.
330Sstevel@tonic-gate */
340Sstevel@tonic-gate
350Sstevel@tonic-gate/*
360Sstevel@tonic-gate * WARNING: If you add a fast trap handler which can be invoked by a
370Sstevel@tonic-gate * non-privileged user, you may have to use the FAST_TRAP_DONE macro
380Sstevel@tonic-gate * instead of "done" instruction to return back to the user mode. See
390Sstevel@tonic-gate * comments for the "fast_trap_done" entry point for more information.
400Sstevel@tonic-gate */
410Sstevel@tonic-gate#define	FAST_TRAP_DONE	\
420Sstevel@tonic-gate	ba,a	fast_trap_done
430Sstevel@tonic-gate
4411172SHaik.Aftandilian@Sun.COM#include <sys/machclock.h>
450Sstevel@tonic-gate#include <sys/clock.h>
460Sstevel@tonic-gate
470Sstevel@tonic-gate#if defined(lint)
480Sstevel@tonic-gate#include <sys/types.h>
490Sstevel@tonic-gate#include <sys/scb.h>
500Sstevel@tonic-gate#include <sys/systm.h>
510Sstevel@tonic-gate#include <sys/regset.h>
520Sstevel@tonic-gate#include <sys/sunddi.h>
530Sstevel@tonic-gate#include <sys/lockstat.h>
540Sstevel@tonic-gate#endif	/* lint */
550Sstevel@tonic-gate
560Sstevel@tonic-gate
570Sstevel@tonic-gate#include <sys/asm_linkage.h>
580Sstevel@tonic-gate#include <sys/privregs.h>
592241Shuah#include <vm/hat_sfmmu.h>
600Sstevel@tonic-gate#include <sys/machparam.h>	/* To get SYSBASE and PAGESIZE */
610Sstevel@tonic-gate#include <sys/machthread.h>
620Sstevel@tonic-gate#include <sys/clock.h>
630Sstevel@tonic-gate#include <sys/intreg.h>
640Sstevel@tonic-gate#include <sys/psr_compat.h>
650Sstevel@tonic-gate#include <sys/isa_defs.h>
660Sstevel@tonic-gate#include <sys/dditypes.h>
670Sstevel@tonic-gate#include <sys/intr.h>
680Sstevel@tonic-gate#include <sys/hypervisor_api.h>
690Sstevel@tonic-gate
700Sstevel@tonic-gate#if !defined(lint)
710Sstevel@tonic-gate#include "assym.h"
720Sstevel@tonic-gate#endif
730Sstevel@tonic-gate
740Sstevel@tonic-gate#define	ICACHE_FLUSHSZ	0x20
750Sstevel@tonic-gate
760Sstevel@tonic-gate#if defined(lint)
770Sstevel@tonic-gate/*
780Sstevel@tonic-gate * Softint generated when counter field of tick reg matches value field
790Sstevel@tonic-gate * of tick_cmpr reg
800Sstevel@tonic-gate */
810Sstevel@tonic-gate/*ARGSUSED*/
820Sstevel@tonic-gatevoid
830Sstevel@tonic-gatetickcmpr_set(uint64_t clock_cycles)
840Sstevel@tonic-gate{}
850Sstevel@tonic-gate
860Sstevel@tonic-gate#else   /* lint */
870Sstevel@tonic-gate
880Sstevel@tonic-gate	ENTRY_NP(tickcmpr_set)
890Sstevel@tonic-gate	! get 64-bit clock_cycles interval
900Sstevel@tonic-gate	mov	%o0, %o2
910Sstevel@tonic-gate	mov	8, %o3			! A reasonable initial step size
920Sstevel@tonic-gate1:
930Sstevel@tonic-gate	WR_TICKCMPR(%o2,%o4,%o5,__LINE__)	! Write to TICK_CMPR
940Sstevel@tonic-gate
9511172SHaik.Aftandilian@Sun.COM	GET_NATIVE_TIME(%o0,%o4,%o5,__LINE__)	! Read %tick to confirm the
9611172SHaik.Aftandilian@Sun.COM						! value we wrote was in the
9711172SHaik.Aftandilian@Sun.COM						! future.
980Sstevel@tonic-gate
990Sstevel@tonic-gate	cmp	%o2, %o0		! If the value we wrote was in the
1000Sstevel@tonic-gate	bg,pt	%xcc, 2f		!   future, then blow out of here.
1012241Shuah	  sllx	%o3, 1, %o3		! If not, then double our step size,
1020Sstevel@tonic-gate	ba,pt	%xcc, 1b		!   and take another lap.
1032241Shuah	  add	%o0, %o3, %o2		!
1040Sstevel@tonic-gate2:
1050Sstevel@tonic-gate	retl
1062241Shuah	  nop
1070Sstevel@tonic-gate	SET_SIZE(tickcmpr_set)
1080Sstevel@tonic-gate
1090Sstevel@tonic-gate#endif  /* lint */
1100Sstevel@tonic-gate
1110Sstevel@tonic-gate#if defined(lint)
1120Sstevel@tonic-gate
1130Sstevel@tonic-gatevoid
1140Sstevel@tonic-gatetickcmpr_disable(void)
1150Sstevel@tonic-gate{}
1160Sstevel@tonic-gate
1170Sstevel@tonic-gate#else
1180Sstevel@tonic-gate
1190Sstevel@tonic-gate	ENTRY_NP(tickcmpr_disable)
1200Sstevel@tonic-gate	mov	1, %g1
1210Sstevel@tonic-gate	sllx	%g1, TICKINT_DIS_SHFT, %o0
1220Sstevel@tonic-gate	WR_TICKCMPR(%o0,%o4,%o5,__LINE__)	! Write to TICK_CMPR
1230Sstevel@tonic-gate	retl
1242241Shuah	  nop
1250Sstevel@tonic-gate	SET_SIZE(tickcmpr_disable)
1260Sstevel@tonic-gate
1270Sstevel@tonic-gate#endif
1280Sstevel@tonic-gate
1290Sstevel@tonic-gate#if defined(lint)
1300Sstevel@tonic-gate
1310Sstevel@tonic-gate/*
13212015SHaik.Aftandilian@Sun.COM * tick_write_delta() is intended to increment %stick by the specified delta,
13312015SHaik.Aftandilian@Sun.COM * but %stick is only writeable in hyperprivileged mode and at present there
13412015SHaik.Aftandilian@Sun.COM * is no provision for this. tick_write_delta is called by the cylic subsystem
13512015SHaik.Aftandilian@Sun.COM * if a negative %stick delta is observed after cyclic processing is resumed
13612015SHaik.Aftandilian@Sun.COM * after an event such as an OS suspend/resume. On sun4v, the suspend/resume
13712015SHaik.Aftandilian@Sun.COM * routines should adjust the %stick offset preventing the cyclic subsystem
13812015SHaik.Aftandilian@Sun.COM * from detecting a negative delta. If a negative delta is detected, panic the
13912015SHaik.Aftandilian@Sun.COM * system. The negative delta could be caused by improper %stick
14012015SHaik.Aftandilian@Sun.COM * synchronization after a suspend/resume.
1410Sstevel@tonic-gate */
1420Sstevel@tonic-gate
1430Sstevel@tonic-gate/*ARGSUSED*/
1440Sstevel@tonic-gatevoid
1450Sstevel@tonic-gatetick_write_delta(uint64_t delta)
1460Sstevel@tonic-gate{}
1470Sstevel@tonic-gate
1480Sstevel@tonic-gate#else	/* lint */
1490Sstevel@tonic-gate
1500Sstevel@tonic-gate	.seg	".text"
1510Sstevel@tonic-gatetick_write_delta_panic:
15212015SHaik.Aftandilian@Sun.COM	.asciz	"tick_write_delta: not supported, delta: 0x%lx"
1530Sstevel@tonic-gate
1540Sstevel@tonic-gate	ENTRY_NP(tick_write_delta)
1550Sstevel@tonic-gate	sethi	%hi(tick_write_delta_panic), %o1
1560Sstevel@tonic-gate        save    %sp, -SA(MINFRAME), %sp ! get a new window to preserve caller
15712015SHaik.Aftandilian@Sun.COM	mov	%i0, %o1
1580Sstevel@tonic-gate	call	panic
1592241Shuah	  or	%i1, %lo(tick_write_delta_panic), %o0
1600Sstevel@tonic-gate	/*NOTREACHED*/
1610Sstevel@tonic-gate	retl
1622241Shuah	  nop
1630Sstevel@tonic-gate#endif
1640Sstevel@tonic-gate
1650Sstevel@tonic-gate#if defined(lint)
1660Sstevel@tonic-gate/*
1670Sstevel@tonic-gate *  return 1 if disabled
1680Sstevel@tonic-gate */
1690Sstevel@tonic-gate
1700Sstevel@tonic-gateint
1710Sstevel@tonic-gatetickcmpr_disabled(void)
1720Sstevel@tonic-gate{ return (0); }
1730Sstevel@tonic-gate
1740Sstevel@tonic-gate#else   /* lint */
1750Sstevel@tonic-gate
1760Sstevel@tonic-gate	ENTRY_NP(tickcmpr_disabled)
17711172SHaik.Aftandilian@Sun.COM	RD_TICKCMPR(%g1,%o0,%o1,__LINE__)
1780Sstevel@tonic-gate	retl
1792241Shuah	  srlx	%g1, TICKINT_DIS_SHFT, %o0
1800Sstevel@tonic-gate	SET_SIZE(tickcmpr_disabled)
1810Sstevel@tonic-gate
1820Sstevel@tonic-gate#endif  /* lint */
1830Sstevel@tonic-gate
1840Sstevel@tonic-gate/*
1850Sstevel@tonic-gate * Get current tick
1860Sstevel@tonic-gate */
1870Sstevel@tonic-gate#if defined(lint)
1880Sstevel@tonic-gate
1890Sstevel@tonic-gateu_longlong_t
1900Sstevel@tonic-gategettick(void)
1910Sstevel@tonic-gate{ return (0); }
1920Sstevel@tonic-gate
193*12908SPavel.Tatashin@Sun.COMu_longlong_t
194*12908SPavel.Tatashin@Sun.COMrandtick(void)
195*12908SPavel.Tatashin@Sun.COM{ return (0); }
196*12908SPavel.Tatashin@Sun.COM
1970Sstevel@tonic-gate#else   /* lint */
1980Sstevel@tonic-gate
1990Sstevel@tonic-gate	ENTRY(gettick)
200*12908SPavel.Tatashin@Sun.COM	ALTENTRY(randtick)
20111172SHaik.Aftandilian@Sun.COM	GET_NATIVE_TIME(%o0,%o2,%o3,__LINE__)
2020Sstevel@tonic-gate	retl
2032241Shuah	  nop
204*12908SPavel.Tatashin@Sun.COM	SET_SIZE(randtick)
2050Sstevel@tonic-gate	SET_SIZE(gettick)
2060Sstevel@tonic-gate
2070Sstevel@tonic-gate#endif  /* lint */
2080Sstevel@tonic-gate
20911172SHaik.Aftandilian@Sun.COM/*
21011172SHaik.Aftandilian@Sun.COM * Get current tick. For trapstat use only.
21111172SHaik.Aftandilian@Sun.COM */
21211172SHaik.Aftandilian@Sun.COM#if defined (lint)
21311172SHaik.Aftandilian@Sun.COM
21411172SHaik.Aftandilian@Sun.COMhrtime_t
21511172SHaik.Aftandilian@Sun.COMrdtick()
21611172SHaik.Aftandilian@Sun.COM{ return (0); }
21711172SHaik.Aftandilian@Sun.COM
21811172SHaik.Aftandilian@Sun.COM#else
21911172SHaik.Aftandilian@Sun.COM	ENTRY(rdtick)
22011172SHaik.Aftandilian@Sun.COM	retl
22111172SHaik.Aftandilian@Sun.COM	RD_TICK_PHYSICAL(%o0)
22211172SHaik.Aftandilian@Sun.COM	SET_SIZE(rdtick)
22311172SHaik.Aftandilian@Sun.COM#endif /* lint */
22411172SHaik.Aftandilian@Sun.COM
2250Sstevel@tonic-gate
2260Sstevel@tonic-gate/*
2270Sstevel@tonic-gate * Return the counter portion of the tick register.
2280Sstevel@tonic-gate */
2290Sstevel@tonic-gate
2300Sstevel@tonic-gate#if defined(lint)
2310Sstevel@tonic-gate
2320Sstevel@tonic-gateuint64_t
2330Sstevel@tonic-gategettick_counter(void)
2340Sstevel@tonic-gate{ return(0); }
2350Sstevel@tonic-gate
23611172SHaik.Aftandilian@Sun.COMuint64_t
23711172SHaik.Aftandilian@Sun.COMgettick_npt(void)
23811172SHaik.Aftandilian@Sun.COM{ return(0); }
23911172SHaik.Aftandilian@Sun.COM
24011172SHaik.Aftandilian@Sun.COMuint64_t
24111172SHaik.Aftandilian@Sun.COMgetstick_npt(void)
24211172SHaik.Aftandilian@Sun.COM{ return(0); }
24311172SHaik.Aftandilian@Sun.COM
2440Sstevel@tonic-gate#else	/* lint */
2450Sstevel@tonic-gate
2460Sstevel@tonic-gate	ENTRY_NP(gettick_counter)
24711172SHaik.Aftandilian@Sun.COM	RD_TICK(%o0,%o1,%o2,__LINE__)
24811172SHaik.Aftandilian@Sun.COM	retl
24911172SHaik.Aftandilian@Sun.COM	nop
25011172SHaik.Aftandilian@Sun.COM	SET_SIZE(gettick_counter)
25111172SHaik.Aftandilian@Sun.COM
25211172SHaik.Aftandilian@Sun.COM	ENTRY_NP(gettick_npt)
25311172SHaik.Aftandilian@Sun.COM	RD_TICK_PHYSICAL(%o0)
2540Sstevel@tonic-gate	retl
25511172SHaik.Aftandilian@Sun.COM	srlx	%o0, 63, %o0
25611172SHaik.Aftandilian@Sun.COM	SET_SIZE(gettick_npt)
25711172SHaik.Aftandilian@Sun.COM
25811172SHaik.Aftandilian@Sun.COM	ENTRY_NP(getstick_npt)
25911172SHaik.Aftandilian@Sun.COM	RD_STICK_PHYSICAL(%o0)
26011172SHaik.Aftandilian@Sun.COM	retl
26111172SHaik.Aftandilian@Sun.COM	srlx	%o0, 63, %o0
26211172SHaik.Aftandilian@Sun.COM	SET_SIZE(getstick_npt)
2630Sstevel@tonic-gate#endif	/* lint */
2640Sstevel@tonic-gate
2650Sstevel@tonic-gate/*
2660Sstevel@tonic-gate * Provide a C callable interface to the trap that reads the hi-res timer.
2670Sstevel@tonic-gate * Returns 64-bit nanosecond timestamp in %o0 and %o1.
2680Sstevel@tonic-gate */
2690Sstevel@tonic-gate
2700Sstevel@tonic-gate#if defined(lint)
2710Sstevel@tonic-gate
2720Sstevel@tonic-gatehrtime_t
2730Sstevel@tonic-gategethrtime(void)
2740Sstevel@tonic-gate{
2750Sstevel@tonic-gate	return ((hrtime_t)0);
2760Sstevel@tonic-gate}
2770Sstevel@tonic-gate
2780Sstevel@tonic-gatehrtime_t
2790Sstevel@tonic-gategethrtime_unscaled(void)
2800Sstevel@tonic-gate{
2810Sstevel@tonic-gate	return ((hrtime_t)0);
2820Sstevel@tonic-gate}
2830Sstevel@tonic-gate
2840Sstevel@tonic-gatehrtime_t
2850Sstevel@tonic-gategethrtime_max(void)
2860Sstevel@tonic-gate{
2870Sstevel@tonic-gate	return ((hrtime_t)0);
2880Sstevel@tonic-gate}
2890Sstevel@tonic-gate
2900Sstevel@tonic-gatevoid
2910Sstevel@tonic-gatescalehrtime(hrtime_t *hrt)
2920Sstevel@tonic-gate{
2930Sstevel@tonic-gate	*hrt = 0;
2940Sstevel@tonic-gate}
2950Sstevel@tonic-gate
2960Sstevel@tonic-gatevoid
2970Sstevel@tonic-gategethrestime(timespec_t *tp)
2980Sstevel@tonic-gate{
2990Sstevel@tonic-gate	tp->tv_sec = 0;
3000Sstevel@tonic-gate	tp->tv_nsec = 0;
3010Sstevel@tonic-gate}
3020Sstevel@tonic-gate
3030Sstevel@tonic-gatetime_t
3040Sstevel@tonic-gategethrestime_sec(void)
3050Sstevel@tonic-gate{
3060Sstevel@tonic-gate	return (0);
3070Sstevel@tonic-gate}
3080Sstevel@tonic-gate
3090Sstevel@tonic-gatevoid
3100Sstevel@tonic-gategethrestime_lasttick(timespec_t *tp)
3110Sstevel@tonic-gate{
3120Sstevel@tonic-gate	tp->tv_sec = 0;
3130Sstevel@tonic-gate	tp->tv_nsec = 0;
3140Sstevel@tonic-gate}
3150Sstevel@tonic-gate
3160Sstevel@tonic-gate/*ARGSUSED*/
3170Sstevel@tonic-gatevoid
3180Sstevel@tonic-gatehres_tick(void)
3190Sstevel@tonic-gate{
3200Sstevel@tonic-gate}
3210Sstevel@tonic-gate
3220Sstevel@tonic-gatevoid
3230Sstevel@tonic-gatepanic_hres_tick(void)
3240Sstevel@tonic-gate{
3250Sstevel@tonic-gate}
3260Sstevel@tonic-gate
3270Sstevel@tonic-gate#else	/* lint */
3280Sstevel@tonic-gate
3290Sstevel@tonic-gate	ENTRY_NP(gethrtime)
33011172SHaik.Aftandilian@Sun.COM	GET_HRTIME(%g1,%o0,%o1,%o2,%o3,%o4,%o5,%g2,__LINE__)
3310Sstevel@tonic-gate							! %g1 = hrtime
3320Sstevel@tonic-gate	retl
3332241Shuah	  mov	%g1, %o0
3340Sstevel@tonic-gate	SET_SIZE(gethrtime)
3350Sstevel@tonic-gate
3360Sstevel@tonic-gate	ENTRY_NP(gethrtime_unscaled)
33711172SHaik.Aftandilian@Sun.COM	GET_NATIVE_TIME(%g1,%o2,%o3,__LINE__)	! %g1 = native time
3380Sstevel@tonic-gate	retl
3392241Shuah	  mov	%g1, %o0
3400Sstevel@tonic-gate	SET_SIZE(gethrtime_unscaled)
3410Sstevel@tonic-gate
3420Sstevel@tonic-gate	ENTRY_NP(gethrtime_waitfree)
3430Sstevel@tonic-gate	ALTENTRY(dtrace_gethrtime)
34411172SHaik.Aftandilian@Sun.COM	GET_NATIVE_TIME(%g1,%o2,%o3,__LINE__)	! %g1 = native time
3450Sstevel@tonic-gate	NATIVE_TIME_TO_NSEC(%g1, %o2, %o3)
3460Sstevel@tonic-gate	retl
3472241Shuah	  mov	%g1, %o0
3480Sstevel@tonic-gate	SET_SIZE(dtrace_gethrtime)
3490Sstevel@tonic-gate	SET_SIZE(gethrtime_waitfree)
3500Sstevel@tonic-gate
3510Sstevel@tonic-gate	ENTRY(gethrtime_max)
3520Sstevel@tonic-gate	NATIVE_TIME_MAX(%g1)
3530Sstevel@tonic-gate	NATIVE_TIME_TO_NSEC(%g1, %o0, %o1)
3540Sstevel@tonic-gate
3550Sstevel@tonic-gate	! hrtime_t's are signed, max hrtime_t must be positive
3560Sstevel@tonic-gate	mov	-1, %o2
3570Sstevel@tonic-gate	brlz,a	%g1, 1f
3582241Shuah	  srlx	%o2, 1, %g1
3590Sstevel@tonic-gate1:
3600Sstevel@tonic-gate	retl
3612241Shuah	  mov	%g1, %o0
3620Sstevel@tonic-gate	SET_SIZE(gethrtime_max)
3630Sstevel@tonic-gate
3640Sstevel@tonic-gate	ENTRY(scalehrtime)
3650Sstevel@tonic-gate	ldx	[%o0], %o1
3660Sstevel@tonic-gate	NATIVE_TIME_TO_NSEC(%o1, %o2, %o3)
3670Sstevel@tonic-gate	retl
3682241Shuah	  stx	%o1, [%o0]
3690Sstevel@tonic-gate	SET_SIZE(scalehrtime)
3700Sstevel@tonic-gate
3710Sstevel@tonic-gate/*
3720Sstevel@tonic-gate * Fast trap to return a timestamp, uses trap window, leaves traps
3730Sstevel@tonic-gate * disabled.  Returns a 64-bit nanosecond timestamp in %o0 and %o1.
3740Sstevel@tonic-gate *
3750Sstevel@tonic-gate * This is the handler for the ST_GETHRTIME trap.
3760Sstevel@tonic-gate */
3770Sstevel@tonic-gate
3780Sstevel@tonic-gate	ENTRY_NP(get_timestamp)
37911172SHaik.Aftandilian@Sun.COM	GET_HRTIME(%g1,%g2,%g3,%g4,%g5,%o0,%o1,%o2,__LINE__)
38011172SHaik.Aftandilian@Sun.COM	! %g1 = hrtime
3810Sstevel@tonic-gate	srlx	%g1, 32, %o0				! %o0 = hi32(%g1)
3820Sstevel@tonic-gate	srl	%g1, 0, %o1				! %o1 = lo32(%g1)
3830Sstevel@tonic-gate	FAST_TRAP_DONE
3840Sstevel@tonic-gate	SET_SIZE(get_timestamp)
3850Sstevel@tonic-gate
3860Sstevel@tonic-gate/*
3870Sstevel@tonic-gate * Macro to convert GET_HRESTIME() bits into a timestamp.
3880Sstevel@tonic-gate *
3890Sstevel@tonic-gate * We use two separate macros so that the platform-dependent GET_HRESTIME()
3900Sstevel@tonic-gate * can be as small as possible; CONV_HRESTIME() implements the generic part.
3910Sstevel@tonic-gate */
3920Sstevel@tonic-gate#define	CONV_HRESTIME(hrestsec, hrestnsec, adj, nslt, nano) \
3930Sstevel@tonic-gate	brz,pt	adj, 3f;		/* no adjustments, it's easy */	\
3940Sstevel@tonic-gate	add	hrestnsec, nslt, hrestnsec; /* hrest.tv_nsec += nslt */	\
3950Sstevel@tonic-gate	brlz,pn	adj, 2f;		/* if hrestime_adj negative */	\
3962399Scth	  srlx	nslt, ADJ_SHIFT, nslt;	/* delay: nslt >>= 4 */		\
3970Sstevel@tonic-gate	subcc	adj, nslt, %g0;		/* hrestime_adj - nslt/16 */	\
3980Sstevel@tonic-gate	movg	%xcc, nslt, adj;	/* adj by min(adj, nslt/16) */	\
3990Sstevel@tonic-gate	ba	3f;			/* go convert to sec/nsec */	\
4002241Shuah	  add	hrestnsec, adj, hrestnsec; /* delay: apply adjustment */ \
4010Sstevel@tonic-gate2:	addcc	adj, nslt, %g0;		/* hrestime_adj + nslt/16 */	\
4020Sstevel@tonic-gate	bge,a,pt %xcc, 3f;		/* is adj less negative? */	\
4032241Shuah	  add	hrestnsec, adj, hrestnsec; /* yes: hrest.nsec += adj */	\
4040Sstevel@tonic-gate	sub	hrestnsec, nslt, hrestnsec; /* no: hrest.nsec -= nslt/16 */ \
4050Sstevel@tonic-gate3:	cmp	hrestnsec, nano;	/* more than a billion? */	\
4060Sstevel@tonic-gate	bl,pt	%xcc, 4f;		/* if not, we're done */	\
4072241Shuah	  nop;				/* delay: do nothing :( */	\
4080Sstevel@tonic-gate	add	hrestsec, 1, hrestsec;	/* hrest.tv_sec++; */		\
4090Sstevel@tonic-gate	sub	hrestnsec, nano, hrestnsec; /* hrest.tv_nsec -= NANOSEC; */	\
4102399Scth	ba,a	3b;			/* check >= billion again */	\
4110Sstevel@tonic-gate4:
4120Sstevel@tonic-gate
4130Sstevel@tonic-gate	ENTRY_NP(gethrestime)
41411172SHaik.Aftandilian@Sun.COM	GET_HRESTIME(%o1,%o2,%o3,%o4,%o5,%g1,%g2,%g3,%g4,__LINE__)
4150Sstevel@tonic-gate	CONV_HRESTIME(%o1, %o2, %o3, %o4, %o5)
4160Sstevel@tonic-gate	stn	%o1, [%o0]
4170Sstevel@tonic-gate	retl
4182241Shuah	  stn	%o2, [%o0 + CLONGSIZE]
4190Sstevel@tonic-gate	SET_SIZE(gethrestime)
4200Sstevel@tonic-gate
4210Sstevel@tonic-gate/*
4220Sstevel@tonic-gate * Similar to gethrestime(), but gethrestime_sec() returns current hrestime
4230Sstevel@tonic-gate * seconds.
4240Sstevel@tonic-gate */
4250Sstevel@tonic-gate	ENTRY_NP(gethrestime_sec)
42611172SHaik.Aftandilian@Sun.COM	GET_HRESTIME(%o0,%o2,%o3,%o4,%o5,%g1,%g2,%g3,%g4,__LINE__)
4270Sstevel@tonic-gate	CONV_HRESTIME(%o0, %o2, %o3, %o4, %o5)
4280Sstevel@tonic-gate	retl					! %o0 current hrestime seconds
4292241Shuah	  nop
4300Sstevel@tonic-gate	SET_SIZE(gethrestime_sec)
4310Sstevel@tonic-gate
4320Sstevel@tonic-gate/*
4330Sstevel@tonic-gate * Returns the hrestime on the last tick.  This is simpler than gethrestime()
4340Sstevel@tonic-gate * and gethrestime_sec():  no conversion is required.  gethrestime_lasttick()
4350Sstevel@tonic-gate * follows the same locking algorithm as GET_HRESTIME and GET_HRTIME,
4360Sstevel@tonic-gate * outlined in detail in clock.h.  (Unlike GET_HRESTIME/GET_HRTIME, we don't
4370Sstevel@tonic-gate * rely on load dependencies to effect the membar #LoadLoad, instead declaring
4380Sstevel@tonic-gate * it explicitly.)
4390Sstevel@tonic-gate */
4400Sstevel@tonic-gate	ENTRY_NP(gethrestime_lasttick)
4410Sstevel@tonic-gate	sethi	%hi(hres_lock), %o1
4420Sstevel@tonic-gate0:
4430Sstevel@tonic-gate	lduw	[%o1 + %lo(hres_lock)], %o2	! Load lock value
4440Sstevel@tonic-gate	membar	#LoadLoad			! Load of lock must complete
4450Sstevel@tonic-gate	andn	%o2, 1, %o2			! Mask off lowest bit
4460Sstevel@tonic-gate	ldn	[%o1 + %lo(hrestime)], %g1	! Seconds.
4470Sstevel@tonic-gate	add	%o1, %lo(hrestime), %o4
4480Sstevel@tonic-gate	ldn	[%o4 + CLONGSIZE], %g2		! Nanoseconds.
4490Sstevel@tonic-gate	membar	#LoadLoad			! All loads must complete
4500Sstevel@tonic-gate	lduw	[%o1 + %lo(hres_lock)], %o3	! Reload lock value
4510Sstevel@tonic-gate	cmp	%o3, %o2			! If lock is locked or has
4520Sstevel@tonic-gate	bne	0b				!   changed, retry.
4532241Shuah	  stn	%g1, [%o0]			! Delay: store seconds
4540Sstevel@tonic-gate	retl
4552241Shuah	  stn	%g2, [%o0 + CLONGSIZE]		! Delay: store nanoseconds
4560Sstevel@tonic-gate	SET_SIZE(gethrestime_lasttick)
4570Sstevel@tonic-gate
4580Sstevel@tonic-gate/*
4590Sstevel@tonic-gate * Fast trap for gettimeofday().  Returns a timestruc_t in %o0 and %o1.
4600Sstevel@tonic-gate *
4610Sstevel@tonic-gate * This is the handler for the ST_GETHRESTIME trap.
4620Sstevel@tonic-gate */
4630Sstevel@tonic-gate
4640Sstevel@tonic-gate	ENTRY_NP(get_hrestime)
46511172SHaik.Aftandilian@Sun.COM	GET_HRESTIME(%o0,%o1,%g1,%g2,%g3,%g4,%g5,%o2,%o3,__LINE__)
4660Sstevel@tonic-gate	CONV_HRESTIME(%o0, %o1, %g1, %g2, %g3)
4670Sstevel@tonic-gate	FAST_TRAP_DONE
4680Sstevel@tonic-gate	SET_SIZE(get_hrestime)
4690Sstevel@tonic-gate
4700Sstevel@tonic-gate/*
4710Sstevel@tonic-gate * Fast trap to return lwp virtual time, uses trap window, leaves traps
4720Sstevel@tonic-gate * disabled.  Returns a 64-bit number in %o0:%o1, which is the number
4730Sstevel@tonic-gate * of nanoseconds consumed.
4740Sstevel@tonic-gate *
4750Sstevel@tonic-gate * This is the handler for the ST_GETHRVTIME trap.
4760Sstevel@tonic-gate *
4770Sstevel@tonic-gate * Register usage:
4780Sstevel@tonic-gate *	%o0, %o1 = return lwp virtual time
4790Sstevel@tonic-gate * 	%o2 = CPU/thread
4800Sstevel@tonic-gate * 	%o3 = lwp
4810Sstevel@tonic-gate * 	%g1 = scratch
4820Sstevel@tonic-gate * 	%g5 = scratch
4830Sstevel@tonic-gate */
4840Sstevel@tonic-gate	ENTRY_NP(get_virtime)
48511172SHaik.Aftandilian@Sun.COM	GET_NATIVE_TIME(%g5,%g1,%g2,__LINE__)	! %g5 = native time in ticks
4860Sstevel@tonic-gate	CPU_ADDR(%g2, %g3)			! CPU struct ptr to %g2
4870Sstevel@tonic-gate	ldn	[%g2 + CPU_THREAD], %g2		! thread pointer to %g2
4880Sstevel@tonic-gate	ldn	[%g2 + T_LWP], %g3		! lwp pointer to %g3
4890Sstevel@tonic-gate
4900Sstevel@tonic-gate	/*
4910Sstevel@tonic-gate	 * Subtract start time of current microstate from time
4920Sstevel@tonic-gate	 * of day to get increment for lwp virtual time.
4930Sstevel@tonic-gate	 */
4940Sstevel@tonic-gate	ldx	[%g3 + LWP_STATE_START], %g1	! ms_state_start
4950Sstevel@tonic-gate	sub	%g5, %g1, %g5
4960Sstevel@tonic-gate
4970Sstevel@tonic-gate	/*
4980Sstevel@tonic-gate	 * Add current value of ms_acct[LMS_USER]
4990Sstevel@tonic-gate	 */
5000Sstevel@tonic-gate	ldx	[%g3 + LWP_ACCT_USER], %g1	! ms_acct[LMS_USER]
5010Sstevel@tonic-gate	add	%g5, %g1, %g5
5020Sstevel@tonic-gate	NATIVE_TIME_TO_NSEC(%g5, %g1, %o0)
5030Sstevel@tonic-gate
5040Sstevel@tonic-gate	srl	%g5, 0, %o1			! %o1 = lo32(%g5)
5050Sstevel@tonic-gate	srlx	%g5, 32, %o0			! %o0 = hi32(%g5)
5060Sstevel@tonic-gate
5070Sstevel@tonic-gate	FAST_TRAP_DONE
5080Sstevel@tonic-gate	SET_SIZE(get_virtime)
5090Sstevel@tonic-gate
5100Sstevel@tonic-gate
5110Sstevel@tonic-gate
5120Sstevel@tonic-gate	.seg	".text"
5130Sstevel@tonic-gatehrtime_base_panic:
5140Sstevel@tonic-gate	.asciz	"hrtime_base stepping back"
5150Sstevel@tonic-gate
5160Sstevel@tonic-gate
5170Sstevel@tonic-gate	ENTRY_NP(hres_tick)
5180Sstevel@tonic-gate	save	%sp, -SA(MINFRAME), %sp	! get a new window
5190Sstevel@tonic-gate
5200Sstevel@tonic-gate	sethi	%hi(hrestime), %l4
5210Sstevel@tonic-gate	ldstub	[%l4 + %lo(hres_lock + HRES_LOCK_OFFSET)], %l5	! try locking
5220Sstevel@tonic-gate7:	tst	%l5
5230Sstevel@tonic-gate	bz,pt	%xcc, 8f			! if we got it, drive on
5242241Shuah	  ld	[%l4 + %lo(nsec_scale)], %l5	! delay: %l5 = scaling factor
5250Sstevel@tonic-gate	ldub	[%l4 + %lo(hres_lock + HRES_LOCK_OFFSET)], %l5
5260Sstevel@tonic-gate9:	tst	%l5
5270Sstevel@tonic-gate	bz,a,pn	%xcc, 7b
5282241Shuah	  ldstub	[%l4 + %lo(hres_lock + HRES_LOCK_OFFSET)], %l5
5290Sstevel@tonic-gate	ba,pt	%xcc, 9b
5302241Shuah	  ldub	[%l4 + %lo(hres_lock + HRES_LOCK_OFFSET)], %l5
5310Sstevel@tonic-gate8:
5320Sstevel@tonic-gate	membar	#StoreLoad|#StoreStore
5330Sstevel@tonic-gate
5340Sstevel@tonic-gate	!
5350Sstevel@tonic-gate	! update hres_last_tick.  %l5 has the scaling factor (nsec_scale).
5360Sstevel@tonic-gate	!
5370Sstevel@tonic-gate	ldx	[%l4 + %lo(hrtime_base)], %g1	! load current hrtime_base
53811172SHaik.Aftandilian@Sun.COM	GET_NATIVE_TIME(%l0,%l3,%l6,__LINE__)	! current native time
5390Sstevel@tonic-gate	stx	%l0, [%l4 + %lo(hres_last_tick)]! prev = current
5400Sstevel@tonic-gate	! convert native time to nsecs
5410Sstevel@tonic-gate	NATIVE_TIME_TO_NSEC_SCALE(%l0, %l5, %l2, NSEC_SHIFT)
5420Sstevel@tonic-gate
5430Sstevel@tonic-gate	sub	%l0, %g1, %i1			! get accurate nsec delta
5440Sstevel@tonic-gate
5450Sstevel@tonic-gate	ldx	[%l4 + %lo(hrtime_base)], %l1
5460Sstevel@tonic-gate	cmp	%l1, %l0
5470Sstevel@tonic-gate	bg,pn	%xcc, 9f
5482241Shuah	  nop
5490Sstevel@tonic-gate
5500Sstevel@tonic-gate	stx	%l0, [%l4 + %lo(hrtime_base)]	! update hrtime_base
5510Sstevel@tonic-gate
5520Sstevel@tonic-gate	!
5530Sstevel@tonic-gate	! apply adjustment, if any
5540Sstevel@tonic-gate	!
5550Sstevel@tonic-gate	ldx	[%l4 + %lo(hrestime_adj)], %l0	! %l0 = hrestime_adj
5560Sstevel@tonic-gate	brz	%l0, 2f
5570Sstevel@tonic-gate						! hrestime_adj == 0 ?
5580Sstevel@tonic-gate						! yes, skip adjustments
5592241Shuah	  clr	%l5				! delay: set adj to zero
5600Sstevel@tonic-gate	tst	%l0				! is hrestime_adj >= 0 ?
5610Sstevel@tonic-gate	bge,pt	%xcc, 1f			! yes, go handle positive case
5622241Shuah	  srl	%i1, ADJ_SHIFT, %l5		! delay: %l5 = adj
5630Sstevel@tonic-gate
5640Sstevel@tonic-gate	addcc	%l0, %l5, %g0			! hrestime_adj < -adj ?
5650Sstevel@tonic-gate	bl,pt	%xcc, 2f			! yes, use current adj
5662241Shuah	  neg	%l5				! delay: %l5 = -adj
5670Sstevel@tonic-gate	ba,pt	%xcc, 2f
5682241Shuah	  mov	%l0, %l5			! no, so set adj = hrestime_adj
5690Sstevel@tonic-gate1:
5700Sstevel@tonic-gate	subcc	%l0, %l5, %g0			! hrestime_adj < adj ?
5710Sstevel@tonic-gate	bl,a,pt	%xcc, 2f			! yes, set adj = hrestime_adj
5722241Shuah	  mov	%l0, %l5			! delay: adj = hrestime_adj
5730Sstevel@tonic-gate2:
5740Sstevel@tonic-gate	ldx	[%l4 + %lo(timedelta)], %l0	! %l0 = timedelta
5750Sstevel@tonic-gate	sub	%l0, %l5, %l0			! timedelta -= adj
5760Sstevel@tonic-gate
5770Sstevel@tonic-gate	stx	%l0, [%l4 + %lo(timedelta)]	! store new timedelta
5780Sstevel@tonic-gate	stx	%l0, [%l4 + %lo(hrestime_adj)]	! hrestime_adj = timedelta
5790Sstevel@tonic-gate
5800Sstevel@tonic-gate	or	%l4, %lo(hrestime), %l2
5810Sstevel@tonic-gate	ldn	[%l2], %i2			! %i2:%i3 = hrestime sec:nsec
5820Sstevel@tonic-gate	ldn	[%l2 + CLONGSIZE], %i3
5830Sstevel@tonic-gate	add	%i3, %l5, %i3			! hrestime.nsec += adj
5840Sstevel@tonic-gate	add	%i3, %i1, %i3			! hrestime.nsec += nslt
5850Sstevel@tonic-gate
5860Sstevel@tonic-gate	set	NANOSEC, %l5			! %l5 = NANOSEC
5870Sstevel@tonic-gate	cmp	%i3, %l5
5880Sstevel@tonic-gate	bl,pt	%xcc, 5f			! if hrestime.tv_nsec < NANOSEC
5892241Shuah	  sethi	%hi(one_sec), %i1		! delay
5900Sstevel@tonic-gate	add	%i2, 0x1, %i2			! hrestime.tv_sec++
5910Sstevel@tonic-gate	sub	%i3, %l5, %i3			! hrestime.tv_nsec - NANOSEC
5920Sstevel@tonic-gate	mov	0x1, %l5
5930Sstevel@tonic-gate	st	%l5, [%i1 + %lo(one_sec)]
5940Sstevel@tonic-gate5:
5950Sstevel@tonic-gate	stn	%i2, [%l2]
5960Sstevel@tonic-gate	stn	%i3, [%l2 + CLONGSIZE]		! store the new hrestime
5970Sstevel@tonic-gate
5980Sstevel@tonic-gate	membar	#StoreStore
5990Sstevel@tonic-gate
6000Sstevel@tonic-gate	ld	[%l4 + %lo(hres_lock)], %i1
6010Sstevel@tonic-gate	inc	%i1				! release lock
6020Sstevel@tonic-gate	st	%i1, [%l4 + %lo(hres_lock)]	! clear hres_lock
6030Sstevel@tonic-gate
6040Sstevel@tonic-gate	ret
6050Sstevel@tonic-gate	restore
6060Sstevel@tonic-gate
6070Sstevel@tonic-gate9:
6080Sstevel@tonic-gate	!
6090Sstevel@tonic-gate	! release hres_lock
6100Sstevel@tonic-gate	!
6110Sstevel@tonic-gate	ld	[%l4 + %lo(hres_lock)], %i1
6120Sstevel@tonic-gate	inc	%i1
6130Sstevel@tonic-gate	st	%i1, [%l4 + %lo(hres_lock)]
6140Sstevel@tonic-gate
6150Sstevel@tonic-gate	sethi	%hi(hrtime_base_panic), %o0
6160Sstevel@tonic-gate	call	panic
6172241Shuah	  or	%o0, %lo(hrtime_base_panic), %o0
6180Sstevel@tonic-gate
6190Sstevel@tonic-gate	SET_SIZE(hres_tick)
6200Sstevel@tonic-gate
6210Sstevel@tonic-gate#endif	/* lint */
6220Sstevel@tonic-gate
6230Sstevel@tonic-gate#if !defined(lint) && !defined(__lint)
6240Sstevel@tonic-gate
6250Sstevel@tonic-gate	.seg	".text"
6260Sstevel@tonic-gatekstat_q_panic_msg:
6270Sstevel@tonic-gate	.asciz	"kstat_q_exit: qlen == 0"
6280Sstevel@tonic-gate
6290Sstevel@tonic-gate	ENTRY(kstat_q_panic)
6300Sstevel@tonic-gate	save	%sp, -SA(MINFRAME), %sp
6310Sstevel@tonic-gate	sethi	%hi(kstat_q_panic_msg), %o0
6320Sstevel@tonic-gate	call	panic
6332241Shuah	  or	%o0, %lo(kstat_q_panic_msg), %o0
6340Sstevel@tonic-gate	/*NOTREACHED*/
6350Sstevel@tonic-gate	SET_SIZE(kstat_q_panic)
6360Sstevel@tonic-gate
6370Sstevel@tonic-gate#define	BRZPN	brz,pn
6380Sstevel@tonic-gate#define	BRZPT	brz,pt
6390Sstevel@tonic-gate
6400Sstevel@tonic-gate#define	KSTAT_Q_UPDATE(QOP, QBR, QZERO, QRETURN, QTYPE) \
6410Sstevel@tonic-gate	ld	[%o0 + QTYPE/**/CNT], %o1;	/* %o1 = old qlen */	\
6420Sstevel@tonic-gate	QOP	%o1, 1, %o2;			/* %o2 = new qlen */	\
6430Sstevel@tonic-gate	QBR	%o1, QZERO;			/* done if qlen == 0 */	\
6440Sstevel@tonic-gate	st	%o2, [%o0 + QTYPE/**/CNT];	/* delay: save qlen */	\
6450Sstevel@tonic-gate	ldx	[%o0 + QTYPE/**/LASTUPDATE], %o3;			\
6460Sstevel@tonic-gate	ldx	[%o0 + QTYPE/**/TIME], %o4;	/* %o4 = old time */	\
6470Sstevel@tonic-gate	ldx	[%o0 + QTYPE/**/LENTIME], %o5;	/* %o5 = old lentime */	\
6480Sstevel@tonic-gate	sub	%g1, %o3, %o2;			/* %o2 = time delta */	\
6490Sstevel@tonic-gate	mulx	%o1, %o2, %o3;			/* %o3 = cur lentime */	\
6500Sstevel@tonic-gate	add	%o4, %o2, %o4;			/* %o4 = new time */	\
6510Sstevel@tonic-gate	add	%o5, %o3, %o5;			/* %o5 = new lentime */	\
6520Sstevel@tonic-gate	stx	%o4, [%o0 + QTYPE/**/TIME];	/* save time */		\
6530Sstevel@tonic-gate	stx	%o5, [%o0 + QTYPE/**/LENTIME];	/* save lentime */	\
6540Sstevel@tonic-gateQRETURN;								\
6550Sstevel@tonic-gate	stx	%g1, [%o0 + QTYPE/**/LASTUPDATE]; /* lastupdate = now */
6560Sstevel@tonic-gate
6570Sstevel@tonic-gate	.align 16
6580Sstevel@tonic-gate	ENTRY(kstat_waitq_enter)
65911172SHaik.Aftandilian@Sun.COM	GET_NATIVE_TIME(%g1,%g2,%g3,__LINE__)
6600Sstevel@tonic-gate	KSTAT_Q_UPDATE(add, BRZPT, 1f, 1:retl, KSTAT_IO_W)
6610Sstevel@tonic-gate	SET_SIZE(kstat_waitq_enter)
6620Sstevel@tonic-gate
6630Sstevel@tonic-gate	.align 16
6640Sstevel@tonic-gate	ENTRY(kstat_waitq_exit)
66511172SHaik.Aftandilian@Sun.COM	GET_NATIVE_TIME(%g1,%g2,%g3,__LINE__)
6660Sstevel@tonic-gate	KSTAT_Q_UPDATE(sub, BRZPN, kstat_q_panic, retl, KSTAT_IO_W)
6670Sstevel@tonic-gate	SET_SIZE(kstat_waitq_exit)
6680Sstevel@tonic-gate
6690Sstevel@tonic-gate	.align 16
6700Sstevel@tonic-gate	ENTRY(kstat_runq_enter)
67111172SHaik.Aftandilian@Sun.COM	GET_NATIVE_TIME(%g1,%g2,%g3,__LINE__)
6720Sstevel@tonic-gate	KSTAT_Q_UPDATE(add, BRZPT, 1f, 1:retl, KSTAT_IO_R)
6730Sstevel@tonic-gate	SET_SIZE(kstat_runq_enter)
6740Sstevel@tonic-gate
6750Sstevel@tonic-gate	.align 16
6760Sstevel@tonic-gate	ENTRY(kstat_runq_exit)
67711172SHaik.Aftandilian@Sun.COM	GET_NATIVE_TIME(%g1,%g2,%g3,__LINE__)
6780Sstevel@tonic-gate	KSTAT_Q_UPDATE(sub, BRZPN, kstat_q_panic, retl, KSTAT_IO_R)
6790Sstevel@tonic-gate	SET_SIZE(kstat_runq_exit)
6800Sstevel@tonic-gate
6810Sstevel@tonic-gate	.align 16
6820Sstevel@tonic-gate	ENTRY(kstat_waitq_to_runq)
68311172SHaik.Aftandilian@Sun.COM	GET_NATIVE_TIME(%g1,%g2,%g3,__LINE__)
6840Sstevel@tonic-gate	KSTAT_Q_UPDATE(sub, BRZPN, kstat_q_panic, 1:, KSTAT_IO_W)
6850Sstevel@tonic-gate	KSTAT_Q_UPDATE(add, BRZPT, 1f, 1:retl, KSTAT_IO_R)
6860Sstevel@tonic-gate	SET_SIZE(kstat_waitq_to_runq)
6870Sstevel@tonic-gate
6880Sstevel@tonic-gate	.align 16
6890Sstevel@tonic-gate	ENTRY(kstat_runq_back_to_waitq)
69011172SHaik.Aftandilian@Sun.COM	GET_NATIVE_TIME(%g1,%g2,%g3,__LINE__)
6910Sstevel@tonic-gate	KSTAT_Q_UPDATE(sub, BRZPN, kstat_q_panic, 1:, KSTAT_IO_R)
6920Sstevel@tonic-gate	KSTAT_Q_UPDATE(add, BRZPT, 1f, 1:retl, KSTAT_IO_W)
6930Sstevel@tonic-gate	SET_SIZE(kstat_runq_back_to_waitq)
6940Sstevel@tonic-gate
6950Sstevel@tonic-gate#endif /* lint */
6960Sstevel@tonic-gate
6970Sstevel@tonic-gate#ifdef lint
6980Sstevel@tonic-gate
6990Sstevel@tonic-gateint64_t timedelta;
7000Sstevel@tonic-gatehrtime_t hres_last_tick;
7014551Ssudheervolatile timestruc_t hrestime;
7020Sstevel@tonic-gateint64_t hrestime_adj;
7034551Ssudheervolatile int hres_lock;
7040Sstevel@tonic-gateuint_t nsec_scale;
7050Sstevel@tonic-gatehrtime_t hrtime_base;
7060Sstevel@tonic-gateint traptrace_use_stick;
7070Sstevel@tonic-gate
7080Sstevel@tonic-gate#else
7090Sstevel@tonic-gate	/*
7100Sstevel@tonic-gate	 *  -- WARNING --
7110Sstevel@tonic-gate	 *
7120Sstevel@tonic-gate	 * The following variables MUST be together on a 128-byte boundary.
7130Sstevel@tonic-gate	 * In addition to the primary performance motivation (having them all
7140Sstevel@tonic-gate	 * on the same cache line(s)), code here and in the GET*TIME() macros
7150Sstevel@tonic-gate	 * assumes that they all have the same high 22 address bits (so
7160Sstevel@tonic-gate	 * there's only one sethi).
7170Sstevel@tonic-gate	 */
7180Sstevel@tonic-gate	.seg	".data"
7190Sstevel@tonic-gate	.global	timedelta, hres_last_tick, hrestime, hrestime_adj
7200Sstevel@tonic-gate	.global	hres_lock, nsec_scale, hrtime_base, traptrace_use_stick
72111172SHaik.Aftandilian@Sun.COM	.global	nsec_shift, adj_shift, native_tick_offset, native_stick_offset
7220Sstevel@tonic-gate
7230Sstevel@tonic-gate	/* XXX - above comment claims 128-bytes is necessary */
7240Sstevel@tonic-gate	.align	64
7250Sstevel@tonic-gatetimedelta:
7260Sstevel@tonic-gate	.word	0, 0		/* int64_t */
7270Sstevel@tonic-gatehres_last_tick:
7280Sstevel@tonic-gate	.word	0, 0		/* hrtime_t */
7290Sstevel@tonic-gatehrestime:
7300Sstevel@tonic-gate	.nword	0, 0		/* 2 longs */
7310Sstevel@tonic-gatehrestime_adj:
7320Sstevel@tonic-gate	.word	0, 0		/* int64_t */
7330Sstevel@tonic-gatehres_lock:
7340Sstevel@tonic-gate	.word	0
7350Sstevel@tonic-gatensec_scale:
7360Sstevel@tonic-gate	.word	0
7370Sstevel@tonic-gatehrtime_base:
7380Sstevel@tonic-gate	.word	0, 0
7390Sstevel@tonic-gatetraptrace_use_stick:
7400Sstevel@tonic-gate	.word	0
7410Sstevel@tonic-gatensec_shift:
7420Sstevel@tonic-gate	.word	NSEC_SHIFT
7430Sstevel@tonic-gateadj_shift:
7440Sstevel@tonic-gate	.word	ADJ_SHIFT
74511172SHaik.Aftandilian@Sun.COM	.align	8
74611172SHaik.Aftandilian@Sun.COMnative_tick_offset:
74711172SHaik.Aftandilian@Sun.COM	.word	0, 0
74811172SHaik.Aftandilian@Sun.COM	.align	8
74911172SHaik.Aftandilian@Sun.COMnative_stick_offset:
75011172SHaik.Aftandilian@Sun.COM	.word	0, 0
7510Sstevel@tonic-gate
7520Sstevel@tonic-gate#endif
7530Sstevel@tonic-gate
7540Sstevel@tonic-gate
7550Sstevel@tonic-gate/*
7560Sstevel@tonic-gate * drv_usecwait(clock_t n)	[DDI/DKI - section 9F]
7570Sstevel@tonic-gate * usec_delay(int n)		[compatibility - should go one day]
7580Sstevel@tonic-gate * Delay by spinning.
7590Sstevel@tonic-gate *
7600Sstevel@tonic-gate * delay for n microseconds.  numbers <= 0 delay 1 usec
7610Sstevel@tonic-gate *
7620Sstevel@tonic-gate * With UltraSPARC-III the combination of supporting mixed-speed CPUs
7630Sstevel@tonic-gate * and variable clock rate for power management requires that we
7640Sstevel@tonic-gate * use %stick to implement this routine.
7650Sstevel@tonic-gate */
7660Sstevel@tonic-gate
7670Sstevel@tonic-gate#if defined(lint)
7680Sstevel@tonic-gate
7690Sstevel@tonic-gate/*ARGSUSED*/
7700Sstevel@tonic-gatevoid
7710Sstevel@tonic-gatedrv_usecwait(clock_t n)
7720Sstevel@tonic-gate{}
7730Sstevel@tonic-gate
7740Sstevel@tonic-gate/*ARGSUSED*/
7750Sstevel@tonic-gatevoid
7760Sstevel@tonic-gateusec_delay(int n)
7770Sstevel@tonic-gate{}
7780Sstevel@tonic-gate
7790Sstevel@tonic-gate#else	/* lint */
7800Sstevel@tonic-gate
7810Sstevel@tonic-gate	ENTRY(drv_usecwait)
7820Sstevel@tonic-gate	ALTENTRY(usec_delay)
7830Sstevel@tonic-gate	brlez,a,pn %o0, 0f
7842241Shuah	  mov	1, %o0
7850Sstevel@tonic-gate0:
7860Sstevel@tonic-gate	sethi	%hi(sticks_per_usec), %o1
7870Sstevel@tonic-gate	lduw	[%o1 + %lo(sticks_per_usec)], %o1
7880Sstevel@tonic-gate	mulx	%o1, %o0, %o1		! Scale usec to ticks
7890Sstevel@tonic-gate	inc	%o1			! We don't start on a tick edge
79011172SHaik.Aftandilian@Sun.COM	GET_NATIVE_TIME(%o2,%o3,%o4,__LINE__)
7910Sstevel@tonic-gate	add	%o1, %o2, %o1
7920Sstevel@tonic-gate
7930Sstevel@tonic-gate1:	cmp	%o1, %o2
79411172SHaik.Aftandilian@Sun.COM	GET_NATIVE_TIME(%o2,%o3,%o4,__LINE__)
7950Sstevel@tonic-gate	bgeu,pt	%xcc, 1b
7962241Shuah	  nop
7970Sstevel@tonic-gate	retl
7982241Shuah	  nop
7990Sstevel@tonic-gate	SET_SIZE(usec_delay)
8000Sstevel@tonic-gate	SET_SIZE(drv_usecwait)
8010Sstevel@tonic-gate#endif	/* lint */
8020Sstevel@tonic-gate
8030Sstevel@tonic-gate#if defined(lint)
8040Sstevel@tonic-gate
8050Sstevel@tonic-gate/* ARGSUSED */
8060Sstevel@tonic-gatevoid
8070Sstevel@tonic-gatepil14_interrupt(int level)
8080Sstevel@tonic-gate{}
8090Sstevel@tonic-gate
8100Sstevel@tonic-gate#else
8110Sstevel@tonic-gate
8120Sstevel@tonic-gate/*
8130Sstevel@tonic-gate * Level-14 interrupt prologue.
8140Sstevel@tonic-gate */
8150Sstevel@tonic-gate	ENTRY_NP(pil14_interrupt)
8160Sstevel@tonic-gate	CPU_ADDR(%g1, %g2)
8170Sstevel@tonic-gate	rdpr	%pil, %g6			! %g6 = interrupted PIL
8180Sstevel@tonic-gate	stn	%g6, [%g1 + CPU_PROFILE_PIL]	! record interrupted PIL
8190Sstevel@tonic-gate	rdpr	%tstate, %g6
8200Sstevel@tonic-gate	rdpr	%tpc, %g5
8210Sstevel@tonic-gate	btst	TSTATE_PRIV, %g6		! trap from supervisor mode?
8220Sstevel@tonic-gate	bnz,a,pt %xcc, 1f
8232241Shuah	  stn	%g5, [%g1 + CPU_PROFILE_PC]	! if so, record kernel PC
8240Sstevel@tonic-gate	stn	%g5, [%g1 + CPU_PROFILE_UPC]	! if not, record user PC
8250Sstevel@tonic-gate	ba	pil_interrupt_common		! must be large-disp branch
8262241Shuah	  stn	%g0, [%g1 + CPU_PROFILE_PC]	! zero kernel PC
8270Sstevel@tonic-gate1:	ba	pil_interrupt_common		! must be large-disp branch
8282241Shuah	  stn	%g0, [%g1 + CPU_PROFILE_UPC]	! zero user PC
8290Sstevel@tonic-gate	SET_SIZE(pil14_interrupt)
8300Sstevel@tonic-gate
8310Sstevel@tonic-gate	ENTRY_NP(tick_rtt)
8320Sstevel@tonic-gate	!
8330Sstevel@tonic-gate	! Load TICK_COMPARE into %o5; if bit 63 is set, then TICK_COMPARE is
8340Sstevel@tonic-gate	! disabled.  If TICK_COMPARE is enabled, we know that we need to
8350Sstevel@tonic-gate	! reenqueue the interrupt request structure.  We'll then check TICKINT
8360Sstevel@tonic-gate	! in SOFTINT; if it's set, then we know that we were in a TICK_COMPARE
8370Sstevel@tonic-gate	! interrupt.  In this case, TICK_COMPARE may have been rewritten
8380Sstevel@tonic-gate	! recently; we'll compare %o5 to the current time to verify that it's
8390Sstevel@tonic-gate	! in the future.
8400Sstevel@tonic-gate	!
8410Sstevel@tonic-gate	! Note that %o5 is live until after 1f.
8420Sstevel@tonic-gate	! XXX - there is a subroutine call while %o5 is live!
8430Sstevel@tonic-gate	!
84411172SHaik.Aftandilian@Sun.COM	RD_TICKCMPR(%o5,%g1,%g2,__LINE__)
8450Sstevel@tonic-gate	srlx	%o5, TICKINT_DIS_SHFT, %g1
8460Sstevel@tonic-gate	brnz,pt	%g1, 2f
8472241Shuah	  nop
8480Sstevel@tonic-gate
8490Sstevel@tonic-gate	rdpr 	%pstate, %g5
8500Sstevel@tonic-gate	andn	%g5, PSTATE_IE, %g1
8510Sstevel@tonic-gate	wrpr	%g0, %g1, %pstate		! Disable vec interrupts
8520Sstevel@tonic-gate
8530Sstevel@tonic-gate	sethi	%hi(cbe_level14_inum), %o1
8542973Sgovinda	ldx	[%o1 + %lo(cbe_level14_inum)], %o1
8550Sstevel@tonic-gate	call	intr_enqueue_req ! preserves %o5 and %g5
8562241Shuah	  mov	PIL_14, %o0
8570Sstevel@tonic-gate
8580Sstevel@tonic-gate	! Check SOFTINT for TICKINT/STICKINT
8590Sstevel@tonic-gate	rd	SOFTINT, %o4
8600Sstevel@tonic-gate	set	(TICK_INT_MASK | STICK_INT_MASK), %o0
8610Sstevel@tonic-gate	andcc	%o4, %o0, %g0
8620Sstevel@tonic-gate	bz,a,pn	%icc, 2f
8632241Shuah	  wrpr	%g0, %g5, %pstate		! Enable vec interrupts
8640Sstevel@tonic-gate
8650Sstevel@tonic-gate	! clear TICKINT/STICKINT
8660Sstevel@tonic-gate	wr	%o0, CLEAR_SOFTINT
8670Sstevel@tonic-gate
8680Sstevel@tonic-gate	!
8690Sstevel@tonic-gate	! Now that we've cleared TICKINT, we can reread %tick and confirm
8700Sstevel@tonic-gate	! that the value we programmed is still in the future.  If it isn't,
8710Sstevel@tonic-gate	! we need to reprogram TICK_COMPARE to fire as soon as possible.
8720Sstevel@tonic-gate	!
87311172SHaik.Aftandilian@Sun.COM	GET_NATIVE_TIME(%o0,%g1,%g2,__LINE__)	! %o0 = tick
8740Sstevel@tonic-gate	cmp	%o5, %o0			! In the future?
8750Sstevel@tonic-gate	bg,a,pt	%xcc, 2f			! Yes, drive on.
8762241Shuah	  wrpr	%g0, %g5, %pstate		!   delay: enable vec intr
8770Sstevel@tonic-gate
8780Sstevel@tonic-gate	!
8790Sstevel@tonic-gate	! If we're here, then we have programmed TICK_COMPARE with a %tick
8800Sstevel@tonic-gate	! which is in the past; we'll now load an initial step size, and loop
8810Sstevel@tonic-gate	! until we've managed to program TICK_COMPARE to fire in the future.
8820Sstevel@tonic-gate	!
8830Sstevel@tonic-gate	mov	8, %o4				! 8 = arbitrary inital step
8840Sstevel@tonic-gate1:	add	%o0, %o4, %o5			! Add the step
8850Sstevel@tonic-gate	WR_TICKCMPR(%o5,%g1,%g2,__LINE__)	! Write to TICK_CMPR
88611172SHaik.Aftandilian@Sun.COM	GET_NATIVE_TIME(%o0,%g1,%g2,__LINE__)	! %o0 = tick
8870Sstevel@tonic-gate	cmp	%o5, %o0			! In the future?
8880Sstevel@tonic-gate	bg,a,pt	%xcc, 2f			! Yes, drive on.
8892241Shuah	  wrpr	%g0, %g5, %pstate		!    delay: enable vec intr
8900Sstevel@tonic-gate	ba	1b				! No, try again.
8912241Shuah	  sllx	%o4, 1, %o4			!    delay: double step size
8920Sstevel@tonic-gate
8930Sstevel@tonic-gate2:	ba	current_thread_complete
8942241Shuah	  nop
8950Sstevel@tonic-gate	SET_SIZE(tick_rtt)
8960Sstevel@tonic-gate
8970Sstevel@tonic-gate#endif /* lint */
8980Sstevel@tonic-gate
8990Sstevel@tonic-gate#if defined(lint)
9008803SJonathan.Haslam@Sun.COM
9018803SJonathan.Haslam@Sun.COM/* ARGSUSED */
9028803SJonathan.Haslam@Sun.COMvoid
9038803SJonathan.Haslam@Sun.COMpil15_interrupt(int level)
9048803SJonathan.Haslam@Sun.COM{}
9058803SJonathan.Haslam@Sun.COM
9068803SJonathan.Haslam@Sun.COM#else   /* lint */
9078803SJonathan.Haslam@Sun.COM
9088803SJonathan.Haslam@Sun.COM/*
9098803SJonathan.Haslam@Sun.COM * Level-15 interrupt prologue.
9108803SJonathan.Haslam@Sun.COM */
9118803SJonathan.Haslam@Sun.COM       ENTRY_NP(pil15_interrupt)
9128803SJonathan.Haslam@Sun.COM       CPU_ADDR(%g1, %g2)
9138803SJonathan.Haslam@Sun.COM       rdpr    %tstate, %g6
9148803SJonathan.Haslam@Sun.COM       rdpr    %tpc, %g5
9158803SJonathan.Haslam@Sun.COM       btst    TSTATE_PRIV, %g6                ! trap from supervisor mode?
9168803SJonathan.Haslam@Sun.COM       bnz,a,pt %xcc, 1f
9178803SJonathan.Haslam@Sun.COM       stn     %g5, [%g1 + CPU_CPCPROFILE_PC]  ! if so, record kernel PC
9188803SJonathan.Haslam@Sun.COM       stn     %g5, [%g1 + CPU_CPCPROFILE_UPC] ! if not, record user PC
9198803SJonathan.Haslam@Sun.COM       ba      pil15_epilogue                  ! must be large-disp branch
9208803SJonathan.Haslam@Sun.COM       stn     %g0, [%g1 + CPU_CPCPROFILE_PC]  ! zero kernel PC
9218803SJonathan.Haslam@Sun.COM1:     ba      pil15_epilogue                  ! must be large-disp branch
9228803SJonathan.Haslam@Sun.COM       stn     %g0, [%g1 + CPU_CPCPROFILE_UPC] ! zero user PC
9238803SJonathan.Haslam@Sun.COM       SET_SIZE(pil15_interrupt)
9248803SJonathan.Haslam@Sun.COM
9258803SJonathan.Haslam@Sun.COM#endif  /* lint */
9268803SJonathan.Haslam@Sun.COM
9278803SJonathan.Haslam@Sun.COM#if defined(lint)
9280Sstevel@tonic-gate/*
9290Sstevel@tonic-gate * Prefetch a page_t for write or read, this assumes a linear
9300Sstevel@tonic-gate * scan of sequential page_t's.
9310Sstevel@tonic-gate */
9320Sstevel@tonic-gate/*ARGSUSED*/
9330Sstevel@tonic-gatevoid
9340Sstevel@tonic-gateprefetch_page_w(void *pp)
9350Sstevel@tonic-gate{}
9360Sstevel@tonic-gate
9370Sstevel@tonic-gate/*ARGSUSED*/
9380Sstevel@tonic-gatevoid
9390Sstevel@tonic-gateprefetch_page_r(void *pp)
9400Sstevel@tonic-gate{}
9410Sstevel@tonic-gate#else	/* lint */
9420Sstevel@tonic-gate
9430Sstevel@tonic-gate/* XXXQ These should be inline templates, not functions */
9440Sstevel@tonic-gate        ENTRY(prefetch_page_w)
9450Sstevel@tonic-gate        retl
9462241Shuah	  nop
9470Sstevel@tonic-gate        SET_SIZE(prefetch_page_w)
9480Sstevel@tonic-gate
9490Sstevel@tonic-gate        ENTRY(prefetch_page_r)
9500Sstevel@tonic-gate        retl
9512241Shuah	  nop
9520Sstevel@tonic-gate        SET_SIZE(prefetch_page_r)
9530Sstevel@tonic-gate
9540Sstevel@tonic-gate#endif	/* lint */
9550Sstevel@tonic-gate
9560Sstevel@tonic-gate#if defined(lint)
9570Sstevel@tonic-gate/*
9580Sstevel@tonic-gate * Prefetch struct smap for write.
9590Sstevel@tonic-gate */
9600Sstevel@tonic-gate/*ARGSUSED*/
9610Sstevel@tonic-gatevoid
9620Sstevel@tonic-gateprefetch_smap_w(void *smp)
9630Sstevel@tonic-gate{}
9640Sstevel@tonic-gate#else	/* lint */
9650Sstevel@tonic-gate
9660Sstevel@tonic-gate/* XXXQ These should be inline templates, not functions */
9670Sstevel@tonic-gate	ENTRY(prefetch_smap_w)
9680Sstevel@tonic-gate	retl
9692241Shuah	  nop
9700Sstevel@tonic-gate	SET_SIZE(prefetch_smap_w)
9710Sstevel@tonic-gate
9720Sstevel@tonic-gate#endif	/* lint */
9730Sstevel@tonic-gate
9740Sstevel@tonic-gate/*
9750Sstevel@tonic-gate * Generic sun4v MMU and Cache operations.
9760Sstevel@tonic-gate */
9770Sstevel@tonic-gate
9780Sstevel@tonic-gate#if defined(lint)
9790Sstevel@tonic-gate
9800Sstevel@tonic-gate/*ARGSUSED*/
9810Sstevel@tonic-gatevoid
9822241Shuahvtag_flushpage(caddr_t vaddr, uint64_t sfmmup)
9830Sstevel@tonic-gate{}
9840Sstevel@tonic-gate
9850Sstevel@tonic-gate/*ARGSUSED*/
9860Sstevel@tonic-gatevoid
9870Sstevel@tonic-gatevtag_flushall(void)
9880Sstevel@tonic-gate{}
9890Sstevel@tonic-gate
9900Sstevel@tonic-gate/*ARGSUSED*/
9910Sstevel@tonic-gatevoid
9920Sstevel@tonic-gatevtag_unmap_perm_tl1(uint64_t vaddr, uint64_t ctxnum)
9930Sstevel@tonic-gate{}
9940Sstevel@tonic-gate
9950Sstevel@tonic-gate/*ARGSUSED*/
9960Sstevel@tonic-gatevoid
9972241Shuahvtag_flushpage_tl1(uint64_t vaddr, uint64_t sfmmup)
9980Sstevel@tonic-gate{}
9990Sstevel@tonic-gate
10000Sstevel@tonic-gate/*ARGSUSED*/
10010Sstevel@tonic-gatevoid
10022241Shuahvtag_flush_pgcnt_tl1(uint64_t vaddr, uint64_t sfmmup_pgcnt)
10030Sstevel@tonic-gate{}
10040Sstevel@tonic-gate
10050Sstevel@tonic-gate/*ARGSUSED*/
10060Sstevel@tonic-gatevoid
10070Sstevel@tonic-gatevtag_flushall_tl1(uint64_t dummy1, uint64_t dummy2)
10080Sstevel@tonic-gate{}
10090Sstevel@tonic-gate
10100Sstevel@tonic-gate/*ARGSUSED*/
10110Sstevel@tonic-gatevoid
10120Sstevel@tonic-gatevac_flushpage(pfn_t pfnum, int vcolor)
10130Sstevel@tonic-gate{}
10140Sstevel@tonic-gate
10150Sstevel@tonic-gate/*ARGSUSED*/
10160Sstevel@tonic-gatevoid
10170Sstevel@tonic-gatevac_flushpage_tl1(uint64_t pfnum, uint64_t vcolor)
10180Sstevel@tonic-gate{}
10190Sstevel@tonic-gate
10200Sstevel@tonic-gate/*ARGSUSED*/
10210Sstevel@tonic-gatevoid
10220Sstevel@tonic-gateflush_instr_mem(caddr_t vaddr, size_t len)
10230Sstevel@tonic-gate{}
10240Sstevel@tonic-gate
10250Sstevel@tonic-gate#else	/* lint */
10260Sstevel@tonic-gate
10270Sstevel@tonic-gate	ENTRY_NP(vtag_flushpage)
10280Sstevel@tonic-gate	/*
10290Sstevel@tonic-gate	 * flush page from the tlb
10300Sstevel@tonic-gate	 *
10310Sstevel@tonic-gate	 * %o0 = vaddr
10322241Shuah	 * %o1 = sfmmup
10330Sstevel@tonic-gate	 */
10342241Shuah	SFMMU_CPU_CNUM(%o1, %g1, %g2)   /* %g1 = sfmmu cnum on this CPU */
10352241Shuah
10362241Shuah	mov	%g1, %o1
10370Sstevel@tonic-gate	mov	MAP_ITLB | MAP_DTLB, %o2
10380Sstevel@tonic-gate	ta	MMU_UNMAP_ADDR
10390Sstevel@tonic-gate	brz,pt	%o0, 1f
10402241Shuah	  nop
10410Sstevel@tonic-gate	ba	panic_bad_hcall
10422241Shuah	  mov	MMU_UNMAP_ADDR, %o1
10430Sstevel@tonic-gate1:
10440Sstevel@tonic-gate 	retl
10452241Shuah	  nop
10460Sstevel@tonic-gate	SET_SIZE(vtag_flushpage)
10470Sstevel@tonic-gate
10480Sstevel@tonic-gate	ENTRY_NP(vtag_flushall)
10490Sstevel@tonic-gate	mov	%g0, %o0	! XXX no cpu list yet
10500Sstevel@tonic-gate	mov	%g0, %o1	! XXX no cpu list yet
10510Sstevel@tonic-gate	mov	MAP_ITLB | MAP_DTLB, %o2
10520Sstevel@tonic-gate	mov	MMU_DEMAP_ALL, %o5
10530Sstevel@tonic-gate	ta	FAST_TRAP
10540Sstevel@tonic-gate	brz,pt	%o0, 1f
10552241Shuah	  nop
10560Sstevel@tonic-gate	ba	panic_bad_hcall
10572241Shuah	  mov	MMU_DEMAP_ALL, %o1
10580Sstevel@tonic-gate1:
10590Sstevel@tonic-gate	retl
10602241Shuah	  nop
10610Sstevel@tonic-gate	SET_SIZE(vtag_flushall)
10620Sstevel@tonic-gate
10630Sstevel@tonic-gate	ENTRY_NP(vtag_unmap_perm_tl1)
10640Sstevel@tonic-gate	/*
10650Sstevel@tonic-gate	 * x-trap to unmap perm map entry
10660Sstevel@tonic-gate	 * %g1 = vaddr
10672241Shuah	 * %g2 = ctxnum (KCONTEXT only)
10680Sstevel@tonic-gate	 */
10690Sstevel@tonic-gate	mov	%o0, %g3
10700Sstevel@tonic-gate	mov	%o1, %g4
10710Sstevel@tonic-gate	mov	%o2, %g5
10720Sstevel@tonic-gate	mov	%o5, %g6
10730Sstevel@tonic-gate	mov	%g1, %o0
10740Sstevel@tonic-gate	mov	%g2, %o1
10750Sstevel@tonic-gate	mov	MAP_ITLB | MAP_DTLB, %o2
10760Sstevel@tonic-gate	mov	UNMAP_PERM_ADDR, %o5
10770Sstevel@tonic-gate	ta	FAST_TRAP
10780Sstevel@tonic-gate	brz,pt	%o0, 1f
10790Sstevel@tonic-gate	nop
10801991Sheppo
10810Sstevel@tonic-gate	mov	PTL1_BAD_HCALL, %g1
10821991Sheppo
10831991Sheppo	cmp	%o0, H_ENOMAP
10841991Sheppo	move	%xcc, PTL1_BAD_HCALL_UNMAP_PERM_ENOMAP, %g1
10851991Sheppo
10861991Sheppo	cmp	%o0, H_EINVAL
10871991Sheppo	move	%xcc, PTL1_BAD_HCALL_UNMAP_PERM_EINVAL, %g1
10881991Sheppo
10891991Sheppo	ba,a	ptl1_panic
10900Sstevel@tonic-gate1:
10910Sstevel@tonic-gate	mov	%g6, %o5
10920Sstevel@tonic-gate	mov	%g5, %o2
10930Sstevel@tonic-gate	mov	%g4, %o1
10940Sstevel@tonic-gate	mov	%g3, %o0
10950Sstevel@tonic-gate	retry
10960Sstevel@tonic-gate	SET_SIZE(vtag_unmap_perm_tl1)
10970Sstevel@tonic-gate
10980Sstevel@tonic-gate	ENTRY_NP(vtag_flushpage_tl1)
10990Sstevel@tonic-gate	/*
11000Sstevel@tonic-gate	 * x-trap to flush page from tlb and tsb
11010Sstevel@tonic-gate	 *
11020Sstevel@tonic-gate	 * %g1 = vaddr, zero-extended on 32-bit kernel
11032241Shuah	 * %g2 = sfmmup
11040Sstevel@tonic-gate	 *
11050Sstevel@tonic-gate	 * assumes TSBE_TAG = 0
11060Sstevel@tonic-gate	 */
11070Sstevel@tonic-gate	srln	%g1, MMU_PAGESHIFT, %g1
11080Sstevel@tonic-gate	slln	%g1, MMU_PAGESHIFT, %g1			/* g1 = vaddr */
11090Sstevel@tonic-gate	mov	%o0, %g3
11100Sstevel@tonic-gate	mov	%o1, %g4
11110Sstevel@tonic-gate	mov	%o2, %g5
11122241Shuah	mov	%g1, %o0			/* vaddr */
11132241Shuah
11142241Shuah	SFMMU_CPU_CNUM(%g2, %o1, %g6)   /* %o1 = sfmmu cnum on this CPU */
11152241Shuah
11160Sstevel@tonic-gate	mov	MAP_ITLB | MAP_DTLB, %o2
11170Sstevel@tonic-gate	ta	MMU_UNMAP_ADDR
11180Sstevel@tonic-gate	brz,pt	%o0, 1f
11190Sstevel@tonic-gate	nop
11202241Shuah	  ba	ptl1_panic
11210Sstevel@tonic-gate	mov	PTL1_BAD_HCALL, %g1
11220Sstevel@tonic-gate1:
11230Sstevel@tonic-gate	mov	%g5, %o2
11240Sstevel@tonic-gate	mov	%g4, %o1
11250Sstevel@tonic-gate	mov	%g3, %o0
11260Sstevel@tonic-gate	membar #Sync
11270Sstevel@tonic-gate	retry
11280Sstevel@tonic-gate	SET_SIZE(vtag_flushpage_tl1)
11290Sstevel@tonic-gate
11300Sstevel@tonic-gate	ENTRY_NP(vtag_flush_pgcnt_tl1)
11310Sstevel@tonic-gate	/*
11320Sstevel@tonic-gate	 * x-trap to flush pgcnt MMU_PAGESIZE pages from tlb
11330Sstevel@tonic-gate	 *
11340Sstevel@tonic-gate	 * %g1 = vaddr, zero-extended on 32-bit kernel
11352241Shuah	 * %g2 = <sfmmup58|pgcnt6>, (pgcnt - 1) is pass'ed in via pgcnt6 bits.
11360Sstevel@tonic-gate	 *
11370Sstevel@tonic-gate	 * NOTE: this handler relies on the fact that no
11380Sstevel@tonic-gate	 *	interrupts or traps can occur during the loop
11390Sstevel@tonic-gate	 *	issuing the TLB_DEMAP operations. It is assumed
11400Sstevel@tonic-gate	 *	that interrupts are disabled and this code is
11410Sstevel@tonic-gate	 *	fetching from the kernel locked text address.
11420Sstevel@tonic-gate	 *
11430Sstevel@tonic-gate	 * assumes TSBE_TAG = 0
11440Sstevel@tonic-gate	 */
11450Sstevel@tonic-gate	srln	%g1, MMU_PAGESHIFT, %g1
11460Sstevel@tonic-gate	slln	%g1, MMU_PAGESHIFT, %g1		/* g1 = vaddr */
11470Sstevel@tonic-gate	mov	%o0, %g3
11480Sstevel@tonic-gate	mov	%o1, %g4
11490Sstevel@tonic-gate	mov	%o2, %g5
11500Sstevel@tonic-gate
11512241Shuah	and	%g2, SFMMU_PGCNT_MASK, %g7	/* g7 = pgcnt - 1 */
11522241Shuah	add	%g7, 1, %g7			/* g7 = pgcnt */
11532241Shuah
11542241Shuah        andn    %g2, SFMMU_PGCNT_MASK, %o0      /* %o0 = sfmmup */
11550Sstevel@tonic-gate
11562241Shuah	SFMMU_CPU_CNUM(%o0, %g2, %g6)    /* %g2 = sfmmu cnum on this CPU */
11572241Shuah
11582241Shuah	set	MMU_PAGESIZE, %g6		/* g6 = pgsize */
11592241Shuah
11602241Shuah1:
11612241Shuah	mov	%g1, %o0			/* vaddr */
11622241Shuah	mov	%g2, %o1			/* cnum */
11630Sstevel@tonic-gate	mov	MAP_ITLB | MAP_DTLB, %o2
11640Sstevel@tonic-gate	ta	MMU_UNMAP_ADDR
11650Sstevel@tonic-gate	brz,pt	%o0, 2f
11662241Shuah	  nop
11670Sstevel@tonic-gate	ba	ptl1_panic
11682241Shuah	  mov	PTL1_BAD_HCALL, %g1
11690Sstevel@tonic-gate2:
11700Sstevel@tonic-gate	deccc	%g7				/* decr pgcnt */
11710Sstevel@tonic-gate	bnz,pt	%icc,1b
11722241Shuah	  add	%g1, %g6, %g1			/* go to nextpage */
11730Sstevel@tonic-gate
11740Sstevel@tonic-gate	mov	%g5, %o2
11750Sstevel@tonic-gate	mov	%g4, %o1
11760Sstevel@tonic-gate	mov	%g3, %o0
11770Sstevel@tonic-gate	membar #Sync
11780Sstevel@tonic-gate	retry
11790Sstevel@tonic-gate	SET_SIZE(vtag_flush_pgcnt_tl1)
11800Sstevel@tonic-gate
11810Sstevel@tonic-gate	! Not implemented on US1/US2
11820Sstevel@tonic-gate	ENTRY_NP(vtag_flushall_tl1)
11830Sstevel@tonic-gate	mov	%o0, %g3
11840Sstevel@tonic-gate	mov	%o1, %g4
11850Sstevel@tonic-gate	mov	%o2, %g5
11860Sstevel@tonic-gate	mov	%o3, %g6	! XXXQ not used?
11870Sstevel@tonic-gate	mov	%o5, %g7
11880Sstevel@tonic-gate	mov	%g0, %o0	! XXX no cpu list yet
11890Sstevel@tonic-gate	mov	%g0, %o1	! XXX no cpu list yet
11900Sstevel@tonic-gate	mov	MAP_ITLB | MAP_DTLB, %o2
11910Sstevel@tonic-gate	mov	MMU_DEMAP_ALL, %o5
11920Sstevel@tonic-gate	ta	FAST_TRAP
11930Sstevel@tonic-gate	brz,pt	%o0, 1f
11942241Shuah	  nop
11950Sstevel@tonic-gate	ba	ptl1_panic
11962241Shuah	  mov	PTL1_BAD_HCALL, %g1
11970Sstevel@tonic-gate1:
11980Sstevel@tonic-gate	mov	%g7, %o5
11990Sstevel@tonic-gate	mov	%g6, %o3	! XXXQ not used?
12000Sstevel@tonic-gate	mov	%g5, %o2
12010Sstevel@tonic-gate	mov	%g4, %o1
12020Sstevel@tonic-gate	mov	%g3, %o0
12030Sstevel@tonic-gate	retry
12040Sstevel@tonic-gate	SET_SIZE(vtag_flushall_tl1)
12050Sstevel@tonic-gate
12060Sstevel@tonic-gate/*
12070Sstevel@tonic-gate * flush_instr_mem:
12080Sstevel@tonic-gate *	Flush a portion of the I-$ starting at vaddr
12090Sstevel@tonic-gate * 	%o0 vaddr
12100Sstevel@tonic-gate *	%o1 bytes to be flushed
12110Sstevel@tonic-gate */
12120Sstevel@tonic-gate
12130Sstevel@tonic-gate	ENTRY(flush_instr_mem)
12140Sstevel@tonic-gate	membar	#StoreStore				! Ensure the stores
12150Sstevel@tonic-gate							! are globally visible
12160Sstevel@tonic-gate1:
12170Sstevel@tonic-gate	flush	%o0
12180Sstevel@tonic-gate	subcc	%o1, ICACHE_FLUSHSZ, %o1		! bytes = bytes-0x20
12190Sstevel@tonic-gate	bgu,pt	%ncc, 1b
12202241Shuah	  add	%o0, ICACHE_FLUSHSZ, %o0		! vaddr = vaddr+0x20
12210Sstevel@tonic-gate
12220Sstevel@tonic-gate	retl
12232241Shuah	  nop
12240Sstevel@tonic-gate	SET_SIZE(flush_instr_mem)
12250Sstevel@tonic-gate
12260Sstevel@tonic-gate#endif /* !lint */
12271614Sjb145095
12287718SJason.Beloro@Sun.COM#if !defined(CUSTOM_FPZERO)
12297718SJason.Beloro@Sun.COM
12301614Sjb145095/*
12311614Sjb145095 * fp_zero() - clear all fp data registers and the fsr
12321614Sjb145095 */
12331614Sjb145095
12341614Sjb145095#if defined(lint) || defined(__lint)
12351614Sjb145095
12361614Sjb145095void
12371614Sjb145095fp_zero(void)
12381614Sjb145095{}
12391614Sjb145095
12401614Sjb145095#else	/* lint */
12411614Sjb145095
12421614Sjb145095.global	fp_zero_zero
12431614Sjb145095.align 8
12441614Sjb145095fp_zero_zero:
12451614Sjb145095	.xword	0
12461614Sjb145095
12471614Sjb145095	ENTRY_NP(fp_zero)
12481614Sjb145095	sethi	%hi(fp_zero_zero), %o0
12497718SJason.Beloro@Sun.COM	ldx	[%o0 + %lo(fp_zero_zero)], %fsr
12501614Sjb145095	ldd	[%o0 + %lo(fp_zero_zero)], %f0
12511614Sjb145095	fmovd	%f0, %f2
12521614Sjb145095	fmovd	%f0, %f4
12531614Sjb145095	fmovd	%f0, %f6
12541614Sjb145095	fmovd	%f0, %f8
12551614Sjb145095	fmovd	%f0, %f10
12561614Sjb145095	fmovd	%f0, %f12
12571614Sjb145095	fmovd	%f0, %f14
12581614Sjb145095	fmovd	%f0, %f16
12591614Sjb145095	fmovd	%f0, %f18
12601614Sjb145095	fmovd	%f0, %f20
12611614Sjb145095	fmovd	%f0, %f22
12621614Sjb145095	fmovd	%f0, %f24
12631614Sjb145095	fmovd	%f0, %f26
12641614Sjb145095	fmovd	%f0, %f28
12651614Sjb145095	fmovd	%f0, %f30
12661614Sjb145095	fmovd	%f0, %f32
12671614Sjb145095	fmovd	%f0, %f34
12681614Sjb145095	fmovd	%f0, %f36
12691614Sjb145095	fmovd	%f0, %f38
12701614Sjb145095	fmovd	%f0, %f40
12711614Sjb145095	fmovd	%f0, %f42
12721614Sjb145095	fmovd	%f0, %f44
12731614Sjb145095	fmovd	%f0, %f46
12741614Sjb145095	fmovd	%f0, %f48
12751614Sjb145095	fmovd	%f0, %f50
12761614Sjb145095	fmovd	%f0, %f52
12771614Sjb145095	fmovd	%f0, %f54
12781614Sjb145095	fmovd	%f0, %f56
12791614Sjb145095	fmovd	%f0, %f58
12801614Sjb145095	fmovd	%f0, %f60
12811614Sjb145095	retl
12821614Sjb145095	fmovd	%f0, %f62
12831614Sjb145095	SET_SIZE(fp_zero)
12841614Sjb145095
12851614Sjb145095#endif	/* lint */
12867718SJason.Beloro@Sun.COM#endif  /* CUSTOM_FPZERO */
1287