Home | History | Annotate | Download | only in cpu
      1      0    stevel /*
      2      0    stevel  * CDDL HEADER START
      3      0    stevel  *
      4      0    stevel  * The contents of this file are subject to the terms of the
      5   1614  jb145095  * Common Development and Distribution License (the "License").
      6   1614  jb145095  * You may not use this file except in compliance with the License.
      7      0    stevel  *
      8      0    stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9      0    stevel  * or http://www.opensolaris.org/os/licensing.
     10      0    stevel  * See the License for the specific language governing permissions
     11      0    stevel  * and limitations under the License.
     12      0    stevel  *
     13      0    stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14      0    stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15      0    stevel  * If applicable, add the following below this CDDL HEADER, with the
     16      0    stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17      0    stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18      0    stevel  *
     19      0    stevel  * CDDL HEADER END
     20      0    stevel  */
     21      0    stevel /*
     22   8803  Jonathan  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23      0    stevel  * Use is subject to license terms.
     24      0    stevel  */
     25      0    stevel 
     26      0    stevel #if !defined(lint)
     27      0    stevel #include "assym.h"
     28      0    stevel #endif
     29      0    stevel 
     30      0    stevel /*
     31      0    stevel  * General assembly language routines.
     32      0    stevel  * It is the intent of this file to contain routines that are
     33      0    stevel  * specific to cpu architecture.
     34      0    stevel  */
     35      0    stevel 
     36      0    stevel /*
     37      0    stevel  * WARNING: If you add a fast trap handler which can be invoked by a
     38      0    stevel  * non-privileged user, you may have to use the FAST_TRAP_DONE macro
     39      0    stevel  * instead of "done" instruction to return back to the user mode. See
     40      0    stevel  * comments for the "fast_trap_done" entry point for more information.
     41      0    stevel  */
     42      0    stevel #define	FAST_TRAP_DONE	\
     43      0    stevel 	ba,a	fast_trap_done
     44      0    stevel 
     45  11172      Haik #include <sys/machclock.h>
     46      0    stevel #include <sys/clock.h>
     47      0    stevel 
     48      0    stevel #if defined(lint)
     49      0    stevel #include <sys/types.h>
     50      0    stevel #include <sys/scb.h>
     51      0    stevel #include <sys/systm.h>
     52      0    stevel #include <sys/regset.h>
     53      0    stevel #include <sys/sunddi.h>
     54      0    stevel #include <sys/lockstat.h>
     55      0    stevel #endif	/* lint */
     56      0    stevel 
     57      0    stevel 
     58      0    stevel #include <sys/asm_linkage.h>
     59      0    stevel #include <sys/privregs.h>
     60   2241      huah #include <vm/hat_sfmmu.h>
     61      0    stevel #include <sys/machparam.h>	/* To get SYSBASE and PAGESIZE */
     62      0    stevel #include <sys/machthread.h>
     63      0    stevel #include <sys/clock.h>
     64      0    stevel #include <sys/intreg.h>
     65      0    stevel #include <sys/psr_compat.h>
     66      0    stevel #include <sys/isa_defs.h>
     67      0    stevel #include <sys/dditypes.h>
     68      0    stevel #include <sys/intr.h>
     69      0    stevel #include <sys/hypervisor_api.h>
     70      0    stevel 
     71      0    stevel #if !defined(lint)
     72      0    stevel #include "assym.h"
     73      0    stevel #endif
     74      0    stevel 
     75      0    stevel #define	ICACHE_FLUSHSZ	0x20
     76      0    stevel 
     77      0    stevel #if defined(lint)
     78      0    stevel /*
     79      0    stevel  * Softint generated when counter field of tick reg matches value field
     80      0    stevel  * of tick_cmpr reg
     81      0    stevel  */
     82      0    stevel /*ARGSUSED*/
     83      0    stevel void
     84      0    stevel tickcmpr_set(uint64_t clock_cycles)
     85      0    stevel {}
     86      0    stevel 
     87      0    stevel #else   /* lint */
     88      0    stevel 
     89      0    stevel 	ENTRY_NP(tickcmpr_set)
     90      0    stevel 	! get 64-bit clock_cycles interval
     91      0    stevel 	mov	%o0, %o2
     92      0    stevel 	mov	8, %o3			! A reasonable initial step size
     93      0    stevel 1:
     94      0    stevel 	WR_TICKCMPR(%o2,%o4,%o5,__LINE__)	! Write to TICK_CMPR
     95      0    stevel 
     96  11172      Haik 	GET_NATIVE_TIME(%o0,%o4,%o5,__LINE__)	! Read %tick to confirm the
     97  11172      Haik 						! value we wrote was in the
     98  11172      Haik 						! future.
     99      0    stevel 
    100      0    stevel 	cmp	%o2, %o0		! If the value we wrote was in the
    101      0    stevel 	bg,pt	%xcc, 2f		!   future, then blow out of here.
    102   2241      huah 	  sllx	%o3, 1, %o3		! If not, then double our step size,
    103      0    stevel 	ba,pt	%xcc, 1b		!   and take another lap.
    104   2241      huah 	  add	%o0, %o3, %o2		!
    105      0    stevel 2:
    106      0    stevel 	retl
    107   2241      huah 	  nop
    108      0    stevel 	SET_SIZE(tickcmpr_set)
    109      0    stevel 
    110      0    stevel #endif  /* lint */
    111      0    stevel 
    112      0    stevel #if defined(lint)
    113      0    stevel 
    114      0    stevel void
    115      0    stevel tickcmpr_disable(void)
    116      0    stevel {}
    117      0    stevel 
    118      0    stevel #else
    119      0    stevel 
    120      0    stevel 	ENTRY_NP(tickcmpr_disable)
    121      0    stevel 	mov	1, %g1
    122      0    stevel 	sllx	%g1, TICKINT_DIS_SHFT, %o0
    123      0    stevel 	WR_TICKCMPR(%o0,%o4,%o5,__LINE__)	! Write to TICK_CMPR
    124      0    stevel 	retl
    125   2241      huah 	  nop
    126      0    stevel 	SET_SIZE(tickcmpr_disable)
    127      0    stevel 
    128      0    stevel #endif
    129      0    stevel 
    130      0    stevel #if defined(lint)
    131      0    stevel 
    132      0    stevel /*
    133      0    stevel  * tick_write_delta() increments %tick by the specified delta.  This should
    134      0    stevel  * only be called after a CPR event to assure that gethrtime() continues to
    135      0    stevel  * increase monotonically.  Obviously, writing %tick needs to de done very
    136      0    stevel  * carefully to avoid introducing unnecessary %tick skew across CPUs.  For
    137      0    stevel  * this reason, we make sure we're i-cache hot before actually writing to
    138      0    stevel  * %tick.
    139      0    stevel  *
    140      0    stevel  * NOTE: No provision for this on sun4v right now.
    141      0    stevel  */
    142      0    stevel 
    143      0    stevel /*ARGSUSED*/
    144      0    stevel void
    145      0    stevel tick_write_delta(uint64_t delta)
    146      0    stevel {}
    147      0    stevel 
    148      0    stevel #else	/* lint */
    149      0    stevel 
    150      0    stevel 	.seg	".text"
    151      0    stevel tick_write_delta_panic:
    152      0    stevel 	.asciz	"tick_write_delta: not supported"
    153      0    stevel 
    154      0    stevel 	ENTRY_NP(tick_write_delta)
    155      0    stevel 	sethi	%hi(tick_write_delta_panic), %o1
    156      0    stevel         save    %sp, -SA(MINFRAME), %sp ! get a new window to preserve caller
    157      0    stevel 	call	panic
    158   2241      huah 	  or	%i1, %lo(tick_write_delta_panic), %o0
    159      0    stevel 	/*NOTREACHED*/
    160      0    stevel 	retl
    161   2241      huah 	  nop
    162      0    stevel #endif
    163      0    stevel 
    164      0    stevel #if defined(lint)
    165      0    stevel /*
    166      0    stevel  *  return 1 if disabled
    167      0    stevel  */
    168      0    stevel 
    169      0    stevel int
    170      0    stevel tickcmpr_disabled(void)
    171      0    stevel { return (0); }
    172      0    stevel 
    173      0    stevel #else   /* lint */
    174      0    stevel 
    175      0    stevel 	ENTRY_NP(tickcmpr_disabled)
    176  11172      Haik 	RD_TICKCMPR(%g1,%o0,%o1,__LINE__)
    177      0    stevel 	retl
    178   2241      huah 	  srlx	%g1, TICKINT_DIS_SHFT, %o0
    179      0    stevel 	SET_SIZE(tickcmpr_disabled)
    180      0    stevel 
    181      0    stevel #endif  /* lint */
    182      0    stevel 
    183      0    stevel /*
    184      0    stevel  * Get current tick
    185      0    stevel  */
    186      0    stevel #if defined(lint)
    187      0    stevel 
    188      0    stevel u_longlong_t
    189      0    stevel gettick(void)
    190      0    stevel { return (0); }
    191      0    stevel 
    192      0    stevel #else   /* lint */
    193      0    stevel 
    194      0    stevel 	ENTRY(gettick)
    195  11172      Haik 	GET_NATIVE_TIME(%o0,%o2,%o3,__LINE__)
    196      0    stevel 	retl
    197   2241      huah 	  nop
    198      0    stevel 	SET_SIZE(gettick)
    199      0    stevel 
    200      0    stevel #endif  /* lint */
    201  11172      Haik 
    202  11172      Haik /*
    203  11172      Haik  * Get current tick. For trapstat use only.
    204  11172      Haik  */
    205  11172      Haik #if defined (lint)
    206  11172      Haik 
    207  11172      Haik hrtime_t
    208  11172      Haik rdtick()
    209  11172      Haik { return (0); }
    210  11172      Haik 
    211  11172      Haik #else
    212  11172      Haik 	ENTRY(rdtick)
    213  11172      Haik 	retl
    214  11172      Haik 	RD_TICK_PHYSICAL(%o0)
    215  11172      Haik 	SET_SIZE(rdtick)
    216  11172      Haik #endif /* lint */
    217      0    stevel 
    218      0    stevel 
    219      0    stevel /*
    220      0    stevel  * Return the counter portion of the tick register.
    221      0    stevel  */
    222      0    stevel 
    223      0    stevel #if defined(lint)
    224      0    stevel 
    225      0    stevel uint64_t
    226      0    stevel gettick_counter(void)
    227      0    stevel { return(0); }
    228      0    stevel 
    229  11172      Haik uint64_t
    230  11172      Haik gettick_npt(void)
    231  11172      Haik { return(0); }
    232  11172      Haik 
    233  11172      Haik uint64_t
    234  11172      Haik getstick_npt(void)
    235  11172      Haik { return(0); }
    236  11172      Haik 
    237      0    stevel #else	/* lint */
    238      0    stevel 
    239      0    stevel 	ENTRY_NP(gettick_counter)
    240  11172      Haik 	RD_TICK(%o0,%o1,%o2,__LINE__)
    241      0    stevel 	retl
    242  11172      Haik 	nop
    243      0    stevel 	SET_SIZE(gettick_counter)
    244  11172      Haik 
    245  11172      Haik 	ENTRY_NP(gettick_npt)
    246  11172      Haik 	RD_TICK_PHYSICAL(%o0)
    247  11172      Haik 	retl
    248  11172      Haik 	srlx	%o0, 63, %o0
    249  11172      Haik 	SET_SIZE(gettick_npt)
    250  11172      Haik 
    251  11172      Haik 	ENTRY_NP(getstick_npt)
    252  11172      Haik 	RD_STICK_PHYSICAL(%o0)
    253  11172      Haik 	retl
    254  11172      Haik 	srlx	%o0, 63, %o0
    255  11172      Haik 	SET_SIZE(getstick_npt)
    256      0    stevel #endif	/* lint */
    257      0    stevel 
    258      0    stevel /*
    259      0    stevel  * Provide a C callable interface to the trap that reads the hi-res timer.
    260      0    stevel  * Returns 64-bit nanosecond timestamp in %o0 and %o1.
    261      0    stevel  */
    262      0    stevel 
    263      0    stevel #if defined(lint)
    264      0    stevel 
    265      0    stevel hrtime_t
    266      0    stevel gethrtime(void)
    267      0    stevel {
    268      0    stevel 	return ((hrtime_t)0);
    269      0    stevel }
    270      0    stevel 
    271      0    stevel hrtime_t
    272      0    stevel gethrtime_unscaled(void)
    273      0    stevel {
    274      0    stevel 	return ((hrtime_t)0);
    275      0    stevel }
    276      0    stevel 
    277      0    stevel hrtime_t
    278      0    stevel gethrtime_max(void)
    279      0    stevel {
    280      0    stevel 	return ((hrtime_t)0);
    281      0    stevel }
    282      0    stevel 
    283      0    stevel void
    284      0    stevel scalehrtime(hrtime_t *hrt)
    285      0    stevel {
    286      0    stevel 	*hrt = 0;
    287      0    stevel }
    288      0    stevel 
    289      0    stevel void
    290      0    stevel gethrestime(timespec_t *tp)
    291      0    stevel {
    292      0    stevel 	tp->tv_sec = 0;
    293      0    stevel 	tp->tv_nsec = 0;
    294      0    stevel }
    295      0    stevel 
    296      0    stevel time_t
    297      0    stevel gethrestime_sec(void)
    298      0    stevel {
    299      0    stevel 	return (0);
    300      0    stevel }
    301      0    stevel 
    302      0    stevel void
    303      0    stevel gethrestime_lasttick(timespec_t *tp)
    304      0    stevel {
    305      0    stevel 	tp->tv_sec = 0;
    306      0    stevel 	tp->tv_nsec = 0;
    307      0    stevel }
    308      0    stevel 
    309      0    stevel /*ARGSUSED*/
    310      0    stevel void
    311      0    stevel hres_tick(void)
    312      0    stevel {
    313      0    stevel }
    314      0    stevel 
    315      0    stevel void
    316      0    stevel panic_hres_tick(void)
    317      0    stevel {
    318      0    stevel }
    319      0    stevel 
    320      0    stevel #else	/* lint */
    321      0    stevel 
    322      0    stevel 	ENTRY_NP(gethrtime)
    323  11172      Haik 	GET_HRTIME(%g1,%o0,%o1,%o2,%o3,%o4,%o5,%g2,__LINE__)
    324      0    stevel 							! %g1 = hrtime
    325      0    stevel 	retl
    326   2241      huah 	  mov	%g1, %o0
    327      0    stevel 	SET_SIZE(gethrtime)
    328      0    stevel 
    329      0    stevel 	ENTRY_NP(gethrtime_unscaled)
    330  11172      Haik 	GET_NATIVE_TIME(%g1,%o2,%o3,__LINE__)	! %g1 = native time
    331      0    stevel 	retl
    332   2241      huah 	  mov	%g1, %o0
    333      0    stevel 	SET_SIZE(gethrtime_unscaled)
    334      0    stevel 
    335      0    stevel 	ENTRY_NP(gethrtime_waitfree)
    336      0    stevel 	ALTENTRY(dtrace_gethrtime)
    337  11172      Haik 	GET_NATIVE_TIME(%g1,%o2,%o3,__LINE__)	! %g1 = native time
    338      0    stevel 	NATIVE_TIME_TO_NSEC(%g1, %o2, %o3)
    339      0    stevel 	retl
    340   2241      huah 	  mov	%g1, %o0
    341      0    stevel 	SET_SIZE(dtrace_gethrtime)
    342      0    stevel 	SET_SIZE(gethrtime_waitfree)
    343      0    stevel 
    344      0    stevel 	ENTRY(gethrtime_max)
    345      0    stevel 	NATIVE_TIME_MAX(%g1)
    346      0    stevel 	NATIVE_TIME_TO_NSEC(%g1, %o0, %o1)
    347      0    stevel 
    348      0    stevel 	! hrtime_t's are signed, max hrtime_t must be positive
    349      0    stevel 	mov	-1, %o2
    350      0    stevel 	brlz,a	%g1, 1f
    351   2241      huah 	  srlx	%o2, 1, %g1
    352      0    stevel 1:
    353      0    stevel 	retl
    354   2241      huah 	  mov	%g1, %o0
    355      0    stevel 	SET_SIZE(gethrtime_max)
    356      0    stevel 
    357      0    stevel 	ENTRY(scalehrtime)
    358      0    stevel 	ldx	[%o0], %o1
    359      0    stevel 	NATIVE_TIME_TO_NSEC(%o1, %o2, %o3)
    360      0    stevel 	retl
    361   2241      huah 	  stx	%o1, [%o0]
    362      0    stevel 	SET_SIZE(scalehrtime)
    363      0    stevel 
    364      0    stevel /*
    365      0    stevel  * Fast trap to return a timestamp, uses trap window, leaves traps
    366      0    stevel  * disabled.  Returns a 64-bit nanosecond timestamp in %o0 and %o1.
    367      0    stevel  *
    368      0    stevel  * This is the handler for the ST_GETHRTIME trap.
    369      0    stevel  */
    370      0    stevel 
    371      0    stevel 	ENTRY_NP(get_timestamp)
    372  11172      Haik 	GET_HRTIME(%g1,%g2,%g3,%g4,%g5,%o0,%o1,%o2,__LINE__)
    373  11172      Haik 	! %g1 = hrtime
    374      0    stevel 	srlx	%g1, 32, %o0				! %o0 = hi32(%g1)
    375      0    stevel 	srl	%g1, 0, %o1				! %o1 = lo32(%g1)
    376      0    stevel 	FAST_TRAP_DONE
    377      0    stevel 	SET_SIZE(get_timestamp)
    378      0    stevel 
    379      0    stevel /*
    380      0    stevel  * Macro to convert GET_HRESTIME() bits into a timestamp.
    381      0    stevel  *
    382      0    stevel  * We use two separate macros so that the platform-dependent GET_HRESTIME()
    383      0    stevel  * can be as small as possible; CONV_HRESTIME() implements the generic part.
    384      0    stevel  */
    385      0    stevel #define	CONV_HRESTIME(hrestsec, hrestnsec, adj, nslt, nano) \
    386      0    stevel 	brz,pt	adj, 3f;		/* no adjustments, it's easy */	\
    387      0    stevel 	add	hrestnsec, nslt, hrestnsec; /* hrest.tv_nsec += nslt */	\
    388      0    stevel 	brlz,pn	adj, 2f;		/* if hrestime_adj negative */	\
    389   2399       cth 	  srlx	nslt, ADJ_SHIFT, nslt;	/* delay: nslt >>= 4 */		\
    390      0    stevel 	subcc	adj, nslt, %g0;		/* hrestime_adj - nslt/16 */	\
    391      0    stevel 	movg	%xcc, nslt, adj;	/* adj by min(adj, nslt/16) */	\
    392      0    stevel 	ba	3f;			/* go convert to sec/nsec */	\
    393   2241      huah 	  add	hrestnsec, adj, hrestnsec; /* delay: apply adjustment */ \
    394      0    stevel 2:	addcc	adj, nslt, %g0;		/* hrestime_adj + nslt/16 */	\
    395      0    stevel 	bge,a,pt %xcc, 3f;		/* is adj less negative? */	\
    396   2241      huah 	  add	hrestnsec, adj, hrestnsec; /* yes: hrest.nsec += adj */	\
    397      0    stevel 	sub	hrestnsec, nslt, hrestnsec; /* no: hrest.nsec -= nslt/16 */ \
    398      0    stevel 3:	cmp	hrestnsec, nano;	/* more than a billion? */	\
    399      0    stevel 	bl,pt	%xcc, 4f;		/* if not, we're done */	\
    400   2241      huah 	  nop;				/* delay: do nothing :( */	\
    401      0    stevel 	add	hrestsec, 1, hrestsec;	/* hrest.tv_sec++; */		\
    402      0    stevel 	sub	hrestnsec, nano, hrestnsec; /* hrest.tv_nsec -= NANOSEC; */	\
    403   2399       cth 	ba,a	3b;			/* check >= billion again */	\
    404      0    stevel 4:
    405      0    stevel 
    406      0    stevel 	ENTRY_NP(gethrestime)
    407  11172      Haik 	GET_HRESTIME(%o1,%o2,%o3,%o4,%o5,%g1,%g2,%g3,%g4,__LINE__)
    408      0    stevel 	CONV_HRESTIME(%o1, %o2, %o3, %o4, %o5)
    409      0    stevel 	stn	%o1, [%o0]
    410      0    stevel 	retl
    411   2241      huah 	  stn	%o2, [%o0 + CLONGSIZE]
    412      0    stevel 	SET_SIZE(gethrestime)
    413      0    stevel 
    414      0    stevel /*
    415      0    stevel  * Similar to gethrestime(), but gethrestime_sec() returns current hrestime
    416      0    stevel  * seconds.
    417      0    stevel  */
    418      0    stevel 	ENTRY_NP(gethrestime_sec)
    419  11172      Haik 	GET_HRESTIME(%o0,%o2,%o3,%o4,%o5,%g1,%g2,%g3,%g4,__LINE__)
    420      0    stevel 	CONV_HRESTIME(%o0, %o2, %o3, %o4, %o5)
    421      0    stevel 	retl					! %o0 current hrestime seconds
    422   2241      huah 	  nop
    423      0    stevel 	SET_SIZE(gethrestime_sec)
    424      0    stevel 
    425      0    stevel /*
    426      0    stevel  * Returns the hrestime on the last tick.  This is simpler than gethrestime()
    427      0    stevel  * and gethrestime_sec():  no conversion is required.  gethrestime_lasttick()
    428      0    stevel  * follows the same locking algorithm as GET_HRESTIME and GET_HRTIME,
    429      0    stevel  * outlined in detail in clock.h.  (Unlike GET_HRESTIME/GET_HRTIME, we don't
    430      0    stevel  * rely on load dependencies to effect the membar #LoadLoad, instead declaring
    431      0    stevel  * it explicitly.)
    432      0    stevel  */
    433      0    stevel 	ENTRY_NP(gethrestime_lasttick)
    434      0    stevel 	sethi	%hi(hres_lock), %o1
    435      0    stevel 0:
    436      0    stevel 	lduw	[%o1 + %lo(hres_lock)], %o2	! Load lock value
    437      0    stevel 	membar	#LoadLoad			! Load of lock must complete
    438      0    stevel 	andn	%o2, 1, %o2			! Mask off lowest bit
    439      0    stevel 	ldn	[%o1 + %lo(hrestime)], %g1	! Seconds.
    440      0    stevel 	add	%o1, %lo(hrestime), %o4
    441      0    stevel 	ldn	[%o4 + CLONGSIZE], %g2		! Nanoseconds.
    442      0    stevel 	membar	#LoadLoad			! All loads must complete
    443      0    stevel 	lduw	[%o1 + %lo(hres_lock)], %o3	! Reload lock value
    444      0    stevel 	cmp	%o3, %o2			! If lock is locked or has
    445      0    stevel 	bne	0b				!   changed, retry.
    446   2241      huah 	  stn	%g1, [%o0]			! Delay: store seconds
    447      0    stevel 	retl
    448   2241      huah 	  stn	%g2, [%o0 + CLONGSIZE]		! Delay: store nanoseconds
    449      0    stevel 	SET_SIZE(gethrestime_lasttick)
    450      0    stevel 
    451      0    stevel /*
    452      0    stevel  * Fast trap for gettimeofday().  Returns a timestruc_t in %o0 and %o1.
    453      0    stevel  *
    454      0    stevel  * This is the handler for the ST_GETHRESTIME trap.
    455      0    stevel  */
    456      0    stevel 
    457      0    stevel 	ENTRY_NP(get_hrestime)
    458  11172      Haik 	GET_HRESTIME(%o0,%o1,%g1,%g2,%g3,%g4,%g5,%o2,%o3,__LINE__)
    459      0    stevel 	CONV_HRESTIME(%o0, %o1, %g1, %g2, %g3)
    460      0    stevel 	FAST_TRAP_DONE
    461      0    stevel 	SET_SIZE(get_hrestime)
    462      0    stevel 
    463      0    stevel /*
    464      0    stevel  * Fast trap to return lwp virtual time, uses trap window, leaves traps
    465      0    stevel  * disabled.  Returns a 64-bit number in %o0:%o1, which is the number
    466      0    stevel  * of nanoseconds consumed.
    467      0    stevel  *
    468      0    stevel  * This is the handler for the ST_GETHRVTIME trap.
    469      0    stevel  *
    470      0    stevel  * Register usage:
    471      0    stevel  *	%o0, %o1 = return lwp virtual time
    472      0    stevel  * 	%o2 = CPU/thread
    473      0    stevel  * 	%o3 = lwp
    474      0    stevel  * 	%g1 = scratch
    475      0    stevel  * 	%g5 = scratch
    476      0    stevel  */
    477      0    stevel 	ENTRY_NP(get_virtime)
    478  11172      Haik 	GET_NATIVE_TIME(%g5,%g1,%g2,__LINE__)	! %g5 = native time in ticks
    479      0    stevel 	CPU_ADDR(%g2, %g3)			! CPU struct ptr to %g2
    480      0    stevel 	ldn	[%g2 + CPU_THREAD], %g2		! thread pointer to %g2
    481      0    stevel 	ldn	[%g2 + T_LWP], %g3		! lwp pointer to %g3
    482      0    stevel 
    483      0    stevel 	/*
    484      0    stevel 	 * Subtract start time of current microstate from time
    485      0    stevel 	 * of day to get increment for lwp virtual time.
    486      0    stevel 	 */
    487      0    stevel 	ldx	[%g3 + LWP_STATE_START], %g1	! ms_state_start
    488      0    stevel 	sub	%g5, %g1, %g5
    489      0    stevel 
    490      0    stevel 	/*
    491      0    stevel 	 * Add current value of ms_acct[LMS_USER]
    492      0    stevel 	 */
    493      0    stevel 	ldx	[%g3 + LWP_ACCT_USER], %g1	! ms_acct[LMS_USER]
    494      0    stevel 	add	%g5, %g1, %g5
    495      0    stevel 	NATIVE_TIME_TO_NSEC(%g5, %g1, %o0)
    496      0    stevel 
    497      0    stevel 	srl	%g5, 0, %o1			! %o1 = lo32(%g5)
    498      0    stevel 	srlx	%g5, 32, %o0			! %o0 = hi32(%g5)
    499      0    stevel 
    500      0    stevel 	FAST_TRAP_DONE
    501      0    stevel 	SET_SIZE(get_virtime)
    502      0    stevel 
    503      0    stevel 
    504      0    stevel 
    505      0    stevel 	.seg	".text"
    506      0    stevel hrtime_base_panic:
    507      0    stevel 	.asciz	"hrtime_base stepping back"
    508      0    stevel 
    509      0    stevel 
    510      0    stevel 	ENTRY_NP(hres_tick)
    511      0    stevel 	save	%sp, -SA(MINFRAME), %sp	! get a new window
    512      0    stevel 
    513      0    stevel 	sethi	%hi(hrestime), %l4
    514      0    stevel 	ldstub	[%l4 + %lo(hres_lock + HRES_LOCK_OFFSET)], %l5	! try locking
    515      0    stevel 7:	tst	%l5
    516      0    stevel 	bz,pt	%xcc, 8f			! if we got it, drive on
    517   2241      huah 	  ld	[%l4 + %lo(nsec_scale)], %l5	! delay: %l5 = scaling factor
    518      0    stevel 	ldub	[%l4 + %lo(hres_lock + HRES_LOCK_OFFSET)], %l5
    519      0    stevel 9:	tst	%l5
    520      0    stevel 	bz,a,pn	%xcc, 7b
    521   2241      huah 	  ldstub	[%l4 + %lo(hres_lock + HRES_LOCK_OFFSET)], %l5
    522      0    stevel 	ba,pt	%xcc, 9b
    523   2241      huah 	  ldub	[%l4 + %lo(hres_lock + HRES_LOCK_OFFSET)], %l5
    524      0    stevel 8:
    525      0    stevel 	membar	#StoreLoad|#StoreStore
    526      0    stevel 
    527      0    stevel 	!
    528      0    stevel 	! update hres_last_tick.  %l5 has the scaling factor (nsec_scale).
    529      0    stevel 	!
    530      0    stevel 	ldx	[%l4 + %lo(hrtime_base)], %g1	! load current hrtime_base
    531  11172      Haik 	GET_NATIVE_TIME(%l0,%l3,%l6,__LINE__)	! current native time
    532      0    stevel 	stx	%l0, [%l4 + %lo(hres_last_tick)]! prev = current
    533      0    stevel 	! convert native time to nsecs
    534      0    stevel 	NATIVE_TIME_TO_NSEC_SCALE(%l0, %l5, %l2, NSEC_SHIFT)
    535      0    stevel 
    536      0    stevel 	sub	%l0, %g1, %i1			! get accurate nsec delta
    537      0    stevel 
    538      0    stevel 	ldx	[%l4 + %lo(hrtime_base)], %l1
    539      0    stevel 	cmp	%l1, %l0
    540      0    stevel 	bg,pn	%xcc, 9f
    541   2241      huah 	  nop
    542      0    stevel 
    543      0    stevel 	stx	%l0, [%l4 + %lo(hrtime_base)]	! update hrtime_base
    544      0    stevel 
    545      0    stevel 	!
    546      0    stevel 	! apply adjustment, if any
    547      0    stevel 	!
    548      0    stevel 	ldx	[%l4 + %lo(hrestime_adj)], %l0	! %l0 = hrestime_adj
    549      0    stevel 	brz	%l0, 2f
    550      0    stevel 						! hrestime_adj == 0 ?
    551      0    stevel 						! yes, skip adjustments
    552   2241      huah 	  clr	%l5				! delay: set adj to zero
    553      0    stevel 	tst	%l0				! is hrestime_adj >= 0 ?
    554      0    stevel 	bge,pt	%xcc, 1f			! yes, go handle positive case
    555   2241      huah 	  srl	%i1, ADJ_SHIFT, %l5		! delay: %l5 = adj
    556      0    stevel 
    557      0    stevel 	addcc	%l0, %l5, %g0			! hrestime_adj < -adj ?
    558      0    stevel 	bl,pt	%xcc, 2f			! yes, use current adj
    559   2241      huah 	  neg	%l5				! delay: %l5 = -adj
    560      0    stevel 	ba,pt	%xcc, 2f
    561   2241      huah 	  mov	%l0, %l5			! no, so set adj = hrestime_adj
    562      0    stevel 1:
    563      0    stevel 	subcc	%l0, %l5, %g0			! hrestime_adj < adj ?
    564      0    stevel 	bl,a,pt	%xcc, 2f			! yes, set adj = hrestime_adj
    565   2241      huah 	  mov	%l0, %l5			! delay: adj = hrestime_adj
    566      0    stevel 2:
    567      0    stevel 	ldx	[%l4 + %lo(timedelta)], %l0	! %l0 = timedelta
    568      0    stevel 	sub	%l0, %l5, %l0			! timedelta -= adj
    569      0    stevel 
    570      0    stevel 	stx	%l0, [%l4 + %lo(timedelta)]	! store new timedelta
    571      0    stevel 	stx	%l0, [%l4 + %lo(hrestime_adj)]	! hrestime_adj = timedelta
    572      0    stevel 
    573      0    stevel 	or	%l4, %lo(hrestime), %l2
    574      0    stevel 	ldn	[%l2], %i2			! %i2:%i3 = hrestime sec:nsec
    575      0    stevel 	ldn	[%l2 + CLONGSIZE], %i3
    576      0    stevel 	add	%i3, %l5, %i3			! hrestime.nsec += adj
    577      0    stevel 	add	%i3, %i1, %i3			! hrestime.nsec += nslt
    578      0    stevel 
    579      0    stevel 	set	NANOSEC, %l5			! %l5 = NANOSEC
    580      0    stevel 	cmp	%i3, %l5
    581      0    stevel 	bl,pt	%xcc, 5f			! if hrestime.tv_nsec < NANOSEC
    582   2241      huah 	  sethi	%hi(one_sec), %i1		! delay
    583      0    stevel 	add	%i2, 0x1, %i2			! hrestime.tv_sec++
    584      0    stevel 	sub	%i3, %l5, %i3			! hrestime.tv_nsec - NANOSEC
    585      0    stevel 	mov	0x1, %l5
    586      0    stevel 	st	%l5, [%i1 + %lo(one_sec)]
    587      0    stevel 5:
    588      0    stevel 	stn	%i2, [%l2]
    589      0    stevel 	stn	%i3, [%l2 + CLONGSIZE]		! store the new hrestime
    590      0    stevel 
    591      0    stevel 	membar	#StoreStore
    592      0    stevel 
    593      0    stevel 	ld	[%l4 + %lo(hres_lock)], %i1
    594      0    stevel 	inc	%i1				! release lock
    595      0    stevel 	st	%i1, [%l4 + %lo(hres_lock)]	! clear hres_lock
    596      0    stevel 
    597      0    stevel 	ret
    598      0    stevel 	restore
    599      0    stevel 
    600      0    stevel 9:
    601      0    stevel 	!
    602      0    stevel 	! release hres_lock
    603      0    stevel 	!
    604      0    stevel 	ld	[%l4 + %lo(hres_lock)], %i1
    605      0    stevel 	inc	%i1
    606      0    stevel 	st	%i1, [%l4 + %lo(hres_lock)]
    607      0    stevel 
    608      0    stevel 	sethi	%hi(hrtime_base_panic), %o0
    609      0    stevel 	call	panic
    610   2241      huah 	  or	%o0, %lo(hrtime_base_panic), %o0
    611      0    stevel 
    612      0    stevel 	SET_SIZE(hres_tick)
    613      0    stevel 
    614      0    stevel #endif	/* lint */
    615      0    stevel 
    616      0    stevel #if !defined(lint) && !defined(__lint)
    617      0    stevel 
    618      0    stevel 	.seg	".text"
    619      0    stevel kstat_q_panic_msg:
    620      0    stevel 	.asciz	"kstat_q_exit: qlen == 0"
    621      0    stevel 
    622      0    stevel 	ENTRY(kstat_q_panic)
    623      0    stevel 	save	%sp, -SA(MINFRAME), %sp
    624      0    stevel 	sethi	%hi(kstat_q_panic_msg), %o0
    625      0    stevel 	call	panic
    626   2241      huah 	  or	%o0, %lo(kstat_q_panic_msg), %o0
    627      0    stevel 	/*NOTREACHED*/
    628      0    stevel 	SET_SIZE(kstat_q_panic)
    629      0    stevel 
    630      0    stevel #define	BRZPN	brz,pn
    631      0    stevel #define	BRZPT	brz,pt
    632      0    stevel 
    633      0    stevel #define	KSTAT_Q_UPDATE(QOP, QBR, QZERO, QRETURN, QTYPE) \
    634      0    stevel 	ld	[%o0 + QTYPE/**/CNT], %o1;	/* %o1 = old qlen */	\
    635      0    stevel 	QOP	%o1, 1, %o2;			/* %o2 = new qlen */	\
    636      0    stevel 	QBR	%o1, QZERO;			/* done if qlen == 0 */	\
    637      0    stevel 	st	%o2, [%o0 + QTYPE/**/CNT];	/* delay: save qlen */	\
    638      0    stevel 	ldx	[%o0 + QTYPE/**/LASTUPDATE], %o3;			\
    639      0    stevel 	ldx	[%o0 + QTYPE/**/TIME], %o4;	/* %o4 = old time */	\
    640      0    stevel 	ldx	[%o0 + QTYPE/**/LENTIME], %o5;	/* %o5 = old lentime */	\
    641      0    stevel 	sub	%g1, %o3, %o2;			/* %o2 = time delta */	\
    642      0    stevel 	mulx	%o1, %o2, %o3;			/* %o3 = cur lentime */	\
    643      0    stevel 	add	%o4, %o2, %o4;			/* %o4 = new time */	\
    644      0    stevel 	add	%o5, %o3, %o5;			/* %o5 = new lentime */	\
    645      0    stevel 	stx	%o4, [%o0 + QTYPE/**/TIME];	/* save time */		\
    646      0    stevel 	stx	%o5, [%o0 + QTYPE/**/LENTIME];	/* save lentime */	\
    647      0    stevel QRETURN;								\
    648      0    stevel 	stx	%g1, [%o0 + QTYPE/**/LASTUPDATE]; /* lastupdate = now */
    649      0    stevel 
    650      0    stevel 	.align 16
    651      0    stevel 	ENTRY(kstat_waitq_enter)
    652  11172      Haik 	GET_NATIVE_TIME(%g1,%g2,%g3,__LINE__)
    653      0    stevel 	KSTAT_Q_UPDATE(add, BRZPT, 1f, 1:retl, KSTAT_IO_W)
    654      0    stevel 	SET_SIZE(kstat_waitq_enter)
    655      0    stevel 
    656      0    stevel 	.align 16
    657      0    stevel 	ENTRY(kstat_waitq_exit)
    658  11172      Haik 	GET_NATIVE_TIME(%g1,%g2,%g3,__LINE__)
    659      0    stevel 	KSTAT_Q_UPDATE(sub, BRZPN, kstat_q_panic, retl, KSTAT_IO_W)
    660      0    stevel 	SET_SIZE(kstat_waitq_exit)
    661      0    stevel 
    662      0    stevel 	.align 16
    663      0    stevel 	ENTRY(kstat_runq_enter)
    664  11172      Haik 	GET_NATIVE_TIME(%g1,%g2,%g3,__LINE__)
    665      0    stevel 	KSTAT_Q_UPDATE(add, BRZPT, 1f, 1:retl, KSTAT_IO_R)
    666      0    stevel 	SET_SIZE(kstat_runq_enter)
    667      0    stevel 
    668      0    stevel 	.align 16
    669      0    stevel 	ENTRY(kstat_runq_exit)
    670  11172      Haik 	GET_NATIVE_TIME(%g1,%g2,%g3,__LINE__)
    671      0    stevel 	KSTAT_Q_UPDATE(sub, BRZPN, kstat_q_panic, retl, KSTAT_IO_R)
    672      0    stevel 	SET_SIZE(kstat_runq_exit)
    673      0    stevel 
    674      0    stevel 	.align 16
    675      0    stevel 	ENTRY(kstat_waitq_to_runq)
    676  11172      Haik 	GET_NATIVE_TIME(%g1,%g2,%g3,__LINE__)
    677      0    stevel 	KSTAT_Q_UPDATE(sub, BRZPN, kstat_q_panic, 1:, KSTAT_IO_W)
    678      0    stevel 	KSTAT_Q_UPDATE(add, BRZPT, 1f, 1:retl, KSTAT_IO_R)
    679      0    stevel 	SET_SIZE(kstat_waitq_to_runq)
    680      0    stevel 
    681      0    stevel 	.align 16
    682      0    stevel 	ENTRY(kstat_runq_back_to_waitq)
    683  11172      Haik 	GET_NATIVE_TIME(%g1,%g2,%g3,__LINE__)
    684      0    stevel 	KSTAT_Q_UPDATE(sub, BRZPN, kstat_q_panic, 1:, KSTAT_IO_R)
    685      0    stevel 	KSTAT_Q_UPDATE(add, BRZPT, 1f, 1:retl, KSTAT_IO_W)
    686      0    stevel 	SET_SIZE(kstat_runq_back_to_waitq)
    687      0    stevel 
    688      0    stevel #endif /* lint */
    689      0    stevel 
    690      0    stevel #ifdef lint
    691      0    stevel 
    692      0    stevel int64_t timedelta;
    693      0    stevel hrtime_t hres_last_tick;
    694   4551   sudheer volatile timestruc_t hrestime;
    695      0    stevel int64_t hrestime_adj;
    696   4551   sudheer volatile int hres_lock;
    697      0    stevel uint_t nsec_scale;
    698      0    stevel hrtime_t hrtime_base;
    699      0    stevel int traptrace_use_stick;
    700      0    stevel 
    701      0    stevel #else
    702      0    stevel 	/*
    703      0    stevel 	 *  -- WARNING --
    704      0    stevel 	 *
    705      0    stevel 	 * The following variables MUST be together on a 128-byte boundary.
    706      0    stevel 	 * In addition to the primary performance motivation (having them all
    707      0    stevel 	 * on the same cache line(s)), code here and in the GET*TIME() macros
    708      0    stevel 	 * assumes that they all have the same high 22 address bits (so
    709      0    stevel 	 * there's only one sethi).
    710      0    stevel 	 */
    711      0    stevel 	.seg	".data"
    712      0    stevel 	.global	timedelta, hres_last_tick, hrestime, hrestime_adj
    713      0    stevel 	.global	hres_lock, nsec_scale, hrtime_base, traptrace_use_stick
    714  11172      Haik 	.global	nsec_shift, adj_shift, native_tick_offset, native_stick_offset
    715      0    stevel 
    716      0    stevel 	/* XXX - above comment claims 128-bytes is necessary */
    717      0    stevel 	.align	64
    718      0    stevel timedelta:
    719      0    stevel 	.word	0, 0		/* int64_t */
    720      0    stevel hres_last_tick:
    721      0    stevel 	.word	0, 0		/* hrtime_t */
    722      0    stevel hrestime:
    723      0    stevel 	.nword	0, 0		/* 2 longs */
    724      0    stevel hrestime_adj:
    725      0    stevel 	.word	0, 0		/* int64_t */
    726      0    stevel hres_lock:
    727      0    stevel 	.word	0
    728      0    stevel nsec_scale:
    729      0    stevel 	.word	0
    730      0    stevel hrtime_base:
    731      0    stevel 	.word	0, 0
    732      0    stevel traptrace_use_stick:
    733      0    stevel 	.word	0
    734      0    stevel nsec_shift:
    735      0    stevel 	.word	NSEC_SHIFT
    736      0    stevel adj_shift:
    737      0    stevel 	.word	ADJ_SHIFT
    738  11172      Haik 	.align	8
    739  11172      Haik native_tick_offset:
    740  11172      Haik 	.word	0, 0
    741  11172      Haik 	.align	8
    742  11172      Haik native_stick_offset:
    743  11172      Haik 	.word	0, 0
    744      0    stevel 
    745      0    stevel #endif
    746      0    stevel 
    747      0    stevel 
    748      0    stevel /*
    749      0    stevel  * drv_usecwait(clock_t n)	[DDI/DKI - section 9F]
    750      0    stevel  * usec_delay(int n)		[compatibility - should go one day]
    751      0    stevel  * Delay by spinning.
    752      0    stevel  *
    753      0    stevel  * delay for n microseconds.  numbers <= 0 delay 1 usec
    754      0    stevel  *
    755      0    stevel  * With UltraSPARC-III the combination of supporting mixed-speed CPUs
    756      0    stevel  * and variable clock rate for power management requires that we
    757      0    stevel  * use %stick to implement this routine.
    758      0    stevel  */
    759      0    stevel 
    760      0    stevel #if defined(lint)
    761      0    stevel 
    762      0    stevel /*ARGSUSED*/
    763      0    stevel void
    764      0    stevel drv_usecwait(clock_t n)
    765      0    stevel {}
    766      0    stevel 
    767      0    stevel /*ARGSUSED*/
    768      0    stevel void
    769      0    stevel usec_delay(int n)
    770      0    stevel {}
    771      0    stevel 
    772      0    stevel #else	/* lint */
    773      0    stevel 
    774      0    stevel 	ENTRY(drv_usecwait)
    775      0    stevel 	ALTENTRY(usec_delay)
    776      0    stevel 	brlez,a,pn %o0, 0f
    777   2241      huah 	  mov	1, %o0
    778      0    stevel 0:
    779      0    stevel 	sethi	%hi(sticks_per_usec), %o1
    780      0    stevel 	lduw	[%o1 + %lo(sticks_per_usec)], %o1
    781      0    stevel 	mulx	%o1, %o0, %o1		! Scale usec to ticks
    782      0    stevel 	inc	%o1			! We don't start on a tick edge
    783  11172      Haik 	GET_NATIVE_TIME(%o2,%o3,%o4,__LINE__)
    784      0    stevel 	add	%o1, %o2, %o1
    785      0    stevel 
    786      0    stevel 1:	cmp	%o1, %o2
    787  11172      Haik 	GET_NATIVE_TIME(%o2,%o3,%o4,__LINE__)
    788      0    stevel 	bgeu,pt	%xcc, 1b
    789   2241      huah 	  nop
    790      0    stevel 	retl
    791   2241      huah 	  nop
    792      0    stevel 	SET_SIZE(usec_delay)
    793      0    stevel 	SET_SIZE(drv_usecwait)
    794      0    stevel #endif	/* lint */
    795      0    stevel 
    796      0    stevel #if defined(lint)
    797      0    stevel 
    798      0    stevel /* ARGSUSED */
    799      0    stevel void
    800      0    stevel pil14_interrupt(int level)
    801      0    stevel {}
    802      0    stevel 
    803      0    stevel #else
    804      0    stevel 
    805      0    stevel /*
    806      0    stevel  * Level-14 interrupt prologue.
    807      0    stevel  */
    808      0    stevel 	ENTRY_NP(pil14_interrupt)
    809      0    stevel 	CPU_ADDR(%g1, %g2)
    810      0    stevel 	rdpr	%pil, %g6			! %g6 = interrupted PIL
    811      0    stevel 	stn	%g6, [%g1 + CPU_PROFILE_PIL]	! record interrupted PIL
    812      0    stevel 	rdpr	%tstate, %g6
    813      0    stevel 	rdpr	%tpc, %g5
    814      0    stevel 	btst	TSTATE_PRIV, %g6		! trap from supervisor mode?
    815      0    stevel 	bnz,a,pt %xcc, 1f
    816   2241      huah 	  stn	%g5, [%g1 + CPU_PROFILE_PC]	! if so, record kernel PC
    817      0    stevel 	stn	%g5, [%g1 + CPU_PROFILE_UPC]	! if not, record user PC
    818      0    stevel 	ba	pil_interrupt_common		! must be large-disp branch
    819   2241      huah 	  stn	%g0, [%g1 + CPU_PROFILE_PC]	! zero kernel PC
    820      0    stevel 1:	ba	pil_interrupt_common		! must be large-disp branch
    821   2241      huah 	  stn	%g0, [%g1 + CPU_PROFILE_UPC]	! zero user PC
    822      0    stevel 	SET_SIZE(pil14_interrupt)
    823      0    stevel 
    824      0    stevel 	ENTRY_NP(tick_rtt)
    825      0    stevel 	!
    826      0    stevel 	! Load TICK_COMPARE into %o5; if bit 63 is set, then TICK_COMPARE is
    827      0    stevel 	! disabled.  If TICK_COMPARE is enabled, we know that we need to
    828      0    stevel 	! reenqueue the interrupt request structure.  We'll then check TICKINT
    829      0    stevel 	! in SOFTINT; if it's set, then we know that we were in a TICK_COMPARE
    830      0    stevel 	! interrupt.  In this case, TICK_COMPARE may have been rewritten
    831      0    stevel 	! recently; we'll compare %o5 to the current time to verify that it's
    832      0    stevel 	! in the future.
    833      0    stevel 	!
    834      0    stevel 	! Note that %o5 is live until after 1f.
    835      0    stevel 	! XXX - there is a subroutine call while %o5 is live!
    836      0    stevel 	!
    837  11172      Haik 	RD_TICKCMPR(%o5,%g1,%g2,__LINE__)
    838      0    stevel 	srlx	%o5, TICKINT_DIS_SHFT, %g1
    839      0    stevel 	brnz,pt	%g1, 2f
    840   2241      huah 	  nop
    841      0    stevel 
    842      0    stevel 	rdpr 	%pstate, %g5
    843      0    stevel 	andn	%g5, PSTATE_IE, %g1
    844      0    stevel 	wrpr	%g0, %g1, %pstate		! Disable vec interrupts
    845      0    stevel 
    846      0    stevel 	sethi	%hi(cbe_level14_inum), %o1
    847   2973   govinda 	ldx	[%o1 + %lo(cbe_level14_inum)], %o1
    848      0    stevel 	call	intr_enqueue_req ! preserves %o5 and %g5
    849   2241      huah 	  mov	PIL_14, %o0
    850      0    stevel 
    851      0    stevel 	! Check SOFTINT for TICKINT/STICKINT
    852      0    stevel 	rd	SOFTINT, %o4
    853      0    stevel 	set	(TICK_INT_MASK | STICK_INT_MASK), %o0
    854      0    stevel 	andcc	%o4, %o0, %g0
    855      0    stevel 	bz,a,pn	%icc, 2f
    856   2241      huah 	  wrpr	%g0, %g5, %pstate		! Enable vec interrupts
    857      0    stevel 
    858      0    stevel 	! clear TICKINT/STICKINT
    859      0    stevel 	wr	%o0, CLEAR_SOFTINT
    860      0    stevel 
    861      0    stevel 	!
    862      0    stevel 	! Now that we've cleared TICKINT, we can reread %tick and confirm
    863      0    stevel 	! that the value we programmed is still in the future.  If it isn't,
    864      0    stevel 	! we need to reprogram TICK_COMPARE to fire as soon as possible.
    865      0    stevel 	!
    866  11172      Haik 	GET_NATIVE_TIME(%o0,%g1,%g2,__LINE__)	! %o0 = tick
    867      0    stevel 	cmp	%o5, %o0			! In the future?
    868      0    stevel 	bg,a,pt	%xcc, 2f			! Yes, drive on.
    869   2241      huah 	  wrpr	%g0, %g5, %pstate		!   delay: enable vec intr
    870      0    stevel 
    871      0    stevel 	!
    872      0    stevel 	! If we're here, then we have programmed TICK_COMPARE with a %tick
    873      0    stevel 	! which is in the past; we'll now load an initial step size, and loop
    874      0    stevel 	! until we've managed to program TICK_COMPARE to fire in the future.
    875      0    stevel 	!
    876      0    stevel 	mov	8, %o4				! 8 = arbitrary inital step
    877      0    stevel 1:	add	%o0, %o4, %o5			! Add the step
    878      0    stevel 	WR_TICKCMPR(%o5,%g1,%g2,__LINE__)	! Write to TICK_CMPR
    879  11172      Haik 	GET_NATIVE_TIME(%o0,%g1,%g2,__LINE__)	! %o0 = tick
    880      0    stevel 	cmp	%o5, %o0			! In the future?
    881      0    stevel 	bg,a,pt	%xcc, 2f			! Yes, drive on.
    882   2241      huah 	  wrpr	%g0, %g5, %pstate		!    delay: enable vec intr
    883      0    stevel 	ba	1b				! No, try again.
    884   2241      huah 	  sllx	%o4, 1, %o4			!    delay: double step size
    885      0    stevel 
    886      0    stevel 2:	ba	current_thread_complete
    887   2241      huah 	  nop
    888      0    stevel 	SET_SIZE(tick_rtt)
    889      0    stevel 
    890      0    stevel #endif /* lint */
    891   8803  Jonathan 
    892   8803  Jonathan #if defined(lint)
    893   8803  Jonathan 
    894   8803  Jonathan /* ARGSUSED */
    895   8803  Jonathan void
    896   8803  Jonathan pil15_interrupt(int level)
    897   8803  Jonathan {}
    898   8803  Jonathan 
    899   8803  Jonathan #else   /* lint */
    900   8803  Jonathan 
    901   8803  Jonathan /*
    902   8803  Jonathan  * Level-15 interrupt prologue.
    903   8803  Jonathan  */
    904   8803  Jonathan        ENTRY_NP(pil15_interrupt)
    905   8803  Jonathan        CPU_ADDR(%g1, %g2)
    906   8803  Jonathan        rdpr    %tstate, %g6
    907   8803  Jonathan        rdpr    %tpc, %g5
    908   8803  Jonathan        btst    TSTATE_PRIV, %g6                ! trap from supervisor mode?
    909   8803  Jonathan        bnz,a,pt %xcc, 1f
    910   8803  Jonathan        stn     %g5, [%g1 + CPU_CPCPROFILE_PC]  ! if so, record kernel PC
    911   8803  Jonathan        stn     %g5, [%g1 + CPU_CPCPROFILE_UPC] ! if not, record user PC
    912   8803  Jonathan        ba      pil15_epilogue                  ! must be large-disp branch
    913   8803  Jonathan        stn     %g0, [%g1 + CPU_CPCPROFILE_PC]  ! zero kernel PC
    914   8803  Jonathan 1:     ba      pil15_epilogue                  ! must be large-disp branch
    915   8803  Jonathan        stn     %g0, [%g1 + CPU_CPCPROFILE_UPC] ! zero user PC
    916   8803  Jonathan        SET_SIZE(pil15_interrupt)
    917   8803  Jonathan 
    918   8803  Jonathan #endif  /* lint */
    919      0    stevel 
    920      0    stevel #if defined(lint)
    921      0    stevel /*
    922      0    stevel  * Prefetch a page_t for write or read, this assumes a linear
    923      0    stevel  * scan of sequential page_t's.
    924      0    stevel  */
    925      0    stevel /*ARGSUSED*/
    926      0    stevel void
    927      0    stevel prefetch_page_w(void *pp)
    928      0    stevel {}
    929      0    stevel 
    930      0    stevel /*ARGSUSED*/
    931      0    stevel void
    932      0    stevel prefetch_page_r(void *pp)
    933      0    stevel {}
    934      0    stevel #else	/* lint */
    935      0    stevel 
    936      0    stevel /* XXXQ These should be inline templates, not functions */
    937      0    stevel         ENTRY(prefetch_page_w)
    938      0    stevel         retl
    939   2241      huah 	  nop
    940      0    stevel         SET_SIZE(prefetch_page_w)
    941      0    stevel 
    942      0    stevel         ENTRY(prefetch_page_r)
    943      0    stevel         retl
    944   2241      huah 	  nop
    945      0    stevel         SET_SIZE(prefetch_page_r)
    946      0    stevel 
    947      0    stevel #endif	/* lint */
    948      0    stevel 
    949      0    stevel #if defined(lint)
    950      0    stevel /*
    951      0    stevel  * Prefetch struct smap for write.
    952      0    stevel  */
    953      0    stevel /*ARGSUSED*/
    954      0    stevel void
    955      0    stevel prefetch_smap_w(void *smp)
    956      0    stevel {}
    957      0    stevel #else	/* lint */
    958      0    stevel 
    959      0    stevel /* XXXQ These should be inline templates, not functions */
    960      0    stevel 	ENTRY(prefetch_smap_w)
    961      0    stevel 	retl
    962   2241      huah 	  nop
    963      0    stevel 	SET_SIZE(prefetch_smap_w)
    964      0    stevel 
    965      0    stevel #endif	/* lint */
    966      0    stevel 
    967      0    stevel /*
    968      0    stevel  * Generic sun4v MMU and Cache operations.
    969      0    stevel  */
    970      0    stevel 
    971      0    stevel #if defined(lint)
    972      0    stevel 
    973      0    stevel /*ARGSUSED*/
    974      0    stevel void
    975   2241      huah vtag_flushpage(caddr_t vaddr, uint64_t sfmmup)
    976      0    stevel {}
    977      0    stevel 
    978      0    stevel /*ARGSUSED*/
    979      0    stevel void
    980      0    stevel vtag_flushall(void)
    981      0    stevel {}
    982      0    stevel 
    983      0    stevel /*ARGSUSED*/
    984      0    stevel void
    985      0    stevel vtag_unmap_perm_tl1(uint64_t vaddr, uint64_t ctxnum)
    986      0    stevel {}
    987      0    stevel 
    988      0    stevel /*ARGSUSED*/
    989      0    stevel void
    990   2241      huah vtag_flushpage_tl1(uint64_t vaddr, uint64_t sfmmup)
    991      0    stevel {}
    992      0    stevel 
    993      0    stevel /*ARGSUSED*/
    994      0    stevel void
    995   2241      huah vtag_flush_pgcnt_tl1(uint64_t vaddr, uint64_t sfmmup_pgcnt)
    996      0    stevel {}
    997      0    stevel 
    998      0    stevel /*ARGSUSED*/
    999      0    stevel void
   1000      0    stevel vtag_flushall_tl1(uint64_t dummy1, uint64_t dummy2)
   1001      0    stevel {}
   1002      0    stevel 
   1003      0    stevel /*ARGSUSED*/
   1004      0    stevel void
   1005      0    stevel vac_flushpage(pfn_t pfnum, int vcolor)
   1006      0    stevel {}
   1007      0    stevel 
   1008      0    stevel /*ARGSUSED*/
   1009      0    stevel void
   1010      0    stevel vac_flushpage_tl1(uint64_t pfnum, uint64_t vcolor)
   1011      0    stevel {}
   1012      0    stevel 
   1013      0    stevel /*ARGSUSED*/
   1014      0    stevel void
   1015      0    stevel flush_instr_mem(caddr_t vaddr, size_t len)
   1016      0    stevel {}
   1017      0    stevel 
   1018      0    stevel #else	/* lint */
   1019      0    stevel 
   1020      0    stevel 	ENTRY_NP(vtag_flushpage)
   1021      0    stevel 	/*
   1022      0    stevel 	 * flush page from the tlb
   1023      0    stevel 	 *
   1024      0    stevel 	 * %o0 = vaddr
   1025   2241      huah 	 * %o1 = sfmmup
   1026      0    stevel 	 */
   1027   2241      huah 	SFMMU_CPU_CNUM(%o1, %g1, %g2)   /* %g1 = sfmmu cnum on this CPU */
   1028   2241      huah 
   1029   2241      huah 	mov	%g1, %o1
   1030      0    stevel 	mov	MAP_ITLB | MAP_DTLB, %o2
   1031      0    stevel 	ta	MMU_UNMAP_ADDR
   1032      0    stevel 	brz,pt	%o0, 1f
   1033   2241      huah 	  nop
   1034      0    stevel 	ba	panic_bad_hcall
   1035   2241      huah 	  mov	MMU_UNMAP_ADDR, %o1
   1036      0    stevel 1:
   1037      0    stevel  	retl
   1038   2241      huah 	  nop
   1039      0    stevel 	SET_SIZE(vtag_flushpage)
   1040      0    stevel 
   1041      0    stevel 	ENTRY_NP(vtag_flushall)
   1042      0    stevel 	mov	%g0, %o0	! XXX no cpu list yet
   1043      0    stevel 	mov	%g0, %o1	! XXX no cpu list yet
   1044      0    stevel 	mov	MAP_ITLB | MAP_DTLB, %o2
   1045      0    stevel 	mov	MMU_DEMAP_ALL, %o5
   1046      0    stevel 	ta	FAST_TRAP
   1047      0    stevel 	brz,pt	%o0, 1f
   1048   2241      huah 	  nop
   1049      0    stevel 	ba	panic_bad_hcall
   1050   2241      huah 	  mov	MMU_DEMAP_ALL, %o1
   1051      0    stevel 1:
   1052      0    stevel 	retl
   1053   2241      huah 	  nop
   1054      0    stevel 	SET_SIZE(vtag_flushall)
   1055      0    stevel 
   1056      0    stevel 	ENTRY_NP(vtag_unmap_perm_tl1)
   1057      0    stevel 	/*
   1058      0    stevel 	 * x-trap to unmap perm map entry
   1059      0    stevel 	 * %g1 = vaddr
   1060   2241      huah 	 * %g2 = ctxnum (KCONTEXT only)
   1061      0    stevel 	 */
   1062      0    stevel 	mov	%o0, %g3
   1063      0    stevel 	mov	%o1, %g4
   1064      0    stevel 	mov	%o2, %g5
   1065      0    stevel 	mov	%o5, %g6
   1066      0    stevel 	mov	%g1, %o0
   1067      0    stevel 	mov	%g2, %o1
   1068      0    stevel 	mov	MAP_ITLB | MAP_DTLB, %o2
   1069      0    stevel 	mov	UNMAP_PERM_ADDR, %o5
   1070      0    stevel 	ta	FAST_TRAP
   1071      0    stevel 	brz,pt	%o0, 1f
   1072      0    stevel 	nop
   1073   1991     heppo 
   1074      0    stevel 	mov	PTL1_BAD_HCALL, %g1
   1075   1991     heppo 
   1076   1991     heppo 	cmp	%o0, H_ENOMAP
   1077   1991     heppo 	move	%xcc, PTL1_BAD_HCALL_UNMAP_PERM_ENOMAP, %g1
   1078   1991     heppo 
   1079   1991     heppo 	cmp	%o0, H_EINVAL
   1080   1991     heppo 	move	%xcc, PTL1_BAD_HCALL_UNMAP_PERM_EINVAL, %g1
   1081   1991     heppo 
   1082   1991     heppo 	ba,a	ptl1_panic
   1083      0    stevel 1:
   1084      0    stevel 	mov	%g6, %o5
   1085      0    stevel 	mov	%g5, %o2
   1086      0    stevel 	mov	%g4, %o1
   1087      0    stevel 	mov	%g3, %o0
   1088      0    stevel 	retry
   1089      0    stevel 	SET_SIZE(vtag_unmap_perm_tl1)
   1090      0    stevel 
   1091      0    stevel 	ENTRY_NP(vtag_flushpage_tl1)
   1092      0    stevel 	/*
   1093      0    stevel 	 * x-trap to flush page from tlb and tsb
   1094      0    stevel 	 *
   1095      0    stevel 	 * %g1 = vaddr, zero-extended on 32-bit kernel
   1096   2241      huah 	 * %g2 = sfmmup
   1097      0    stevel 	 *
   1098      0    stevel 	 * assumes TSBE_TAG = 0
   1099      0    stevel 	 */
   1100      0    stevel 	srln	%g1, MMU_PAGESHIFT, %g1
   1101      0    stevel 	slln	%g1, MMU_PAGESHIFT, %g1			/* g1 = vaddr */
   1102      0    stevel 	mov	%o0, %g3
   1103      0    stevel 	mov	%o1, %g4
   1104      0    stevel 	mov	%o2, %g5
   1105   2241      huah 	mov	%g1, %o0			/* vaddr */
   1106   2241      huah 
   1107   2241      huah 	SFMMU_CPU_CNUM(%g2, %o1, %g6)   /* %o1 = sfmmu cnum on this CPU */
   1108   2241      huah 
   1109      0    stevel 	mov	MAP_ITLB | MAP_DTLB, %o2
   1110      0    stevel 	ta	MMU_UNMAP_ADDR
   1111      0    stevel 	brz,pt	%o0, 1f
   1112      0    stevel 	nop
   1113   2241      huah 	  ba	ptl1_panic
   1114      0    stevel 	mov	PTL1_BAD_HCALL, %g1
   1115      0    stevel 1:
   1116      0    stevel 	mov	%g5, %o2
   1117      0    stevel 	mov	%g4, %o1
   1118      0    stevel 	mov	%g3, %o0
   1119      0    stevel 	membar #Sync
   1120      0    stevel 	retry
   1121      0    stevel 	SET_SIZE(vtag_flushpage_tl1)
   1122      0    stevel 
   1123      0    stevel 	ENTRY_NP(vtag_flush_pgcnt_tl1)
   1124      0    stevel 	/*
   1125      0    stevel 	 * x-trap to flush pgcnt MMU_PAGESIZE pages from tlb
   1126      0    stevel 	 *
   1127      0    stevel 	 * %g1 = vaddr, zero-extended on 32-bit kernel
   1128   2241      huah 	 * %g2 = <sfmmup58|pgcnt6>, (pgcnt - 1) is pass'ed in via pgcnt6 bits.
   1129      0    stevel 	 *
   1130      0    stevel 	 * NOTE: this handler relies on the fact that no
   1131      0    stevel 	 *	interrupts or traps can occur during the loop
   1132      0    stevel 	 *	issuing the TLB_DEMAP operations. It is assumed
   1133      0    stevel 	 *	that interrupts are disabled and this code is
   1134      0    stevel 	 *	fetching from the kernel locked text address.
   1135      0    stevel 	 *
   1136      0    stevel 	 * assumes TSBE_TAG = 0
   1137      0    stevel 	 */
   1138      0    stevel 	srln	%g1, MMU_PAGESHIFT, %g1
   1139      0    stevel 	slln	%g1, MMU_PAGESHIFT, %g1		/* g1 = vaddr */
   1140      0    stevel 	mov	%o0, %g3
   1141      0    stevel 	mov	%o1, %g4
   1142      0    stevel 	mov	%o2, %g5
   1143      0    stevel 
   1144   2241      huah 	and	%g2, SFMMU_PGCNT_MASK, %g7	/* g7 = pgcnt - 1 */
   1145   2241      huah 	add	%g7, 1, %g7			/* g7 = pgcnt */
   1146      0    stevel 
   1147   2241      huah         andn    %g2, SFMMU_PGCNT_MASK, %o0      /* %o0 = sfmmup */
   1148   2241      huah 
   1149   2241      huah 	SFMMU_CPU_CNUM(%o0, %g2, %g6)    /* %g2 = sfmmu cnum on this CPU */
   1150   2241      huah 
   1151   2241      huah 	set	MMU_PAGESIZE, %g6		/* g6 = pgsize */
   1152   2241      huah 
   1153   2241      huah 1:
   1154   2241      huah 	mov	%g1, %o0			/* vaddr */
   1155   2241      huah 	mov	%g2, %o1			/* cnum */
   1156      0    stevel 	mov	MAP_ITLB | MAP_DTLB, %o2
   1157      0    stevel 	ta	MMU_UNMAP_ADDR
   1158      0    stevel 	brz,pt	%o0, 2f
   1159   2241      huah 	  nop
   1160      0    stevel 	ba	ptl1_panic
   1161   2241      huah 	  mov	PTL1_BAD_HCALL, %g1
   1162      0    stevel 2:
   1163      0    stevel 	deccc	%g7				/* decr pgcnt */
   1164      0    stevel 	bnz,pt	%icc,1b
   1165   2241      huah 	  add	%g1, %g6, %g1			/* go to nextpage */
   1166      0    stevel 
   1167      0    stevel 	mov	%g5, %o2
   1168      0    stevel 	mov	%g4, %o1
   1169      0    stevel 	mov	%g3, %o0
   1170      0    stevel 	membar #Sync
   1171      0    stevel 	retry
   1172      0    stevel 	SET_SIZE(vtag_flush_pgcnt_tl1)
   1173      0    stevel 
   1174      0    stevel 	! Not implemented on US1/US2
   1175      0    stevel 	ENTRY_NP(vtag_flushall_tl1)
   1176      0    stevel 	mov	%o0, %g3
   1177      0    stevel 	mov	%o1, %g4
   1178      0    stevel 	mov	%o2, %g5
   1179      0    stevel 	mov	%o3, %g6	! XXXQ not used?
   1180      0    stevel 	mov	%o5, %g7
   1181      0    stevel 	mov	%g0, %o0	! XXX no cpu list yet
   1182      0    stevel 	mov	%g0, %o1	! XXX no cpu list yet
   1183      0    stevel 	mov	MAP_ITLB | MAP_DTLB, %o2
   1184      0    stevel 	mov	MMU_DEMAP_ALL, %o5
   1185      0    stevel 	ta	FAST_TRAP
   1186      0    stevel 	brz,pt	%o0, 1f
   1187   2241      huah 	  nop
   1188      0    stevel 	ba	ptl1_panic
   1189   2241      huah 	  mov	PTL1_BAD_HCALL, %g1
   1190      0    stevel 1:
   1191      0    stevel 	mov	%g7, %o5
   1192      0    stevel 	mov	%g6, %o3	! XXXQ not used?
   1193      0    stevel 	mov	%g5, %o2
   1194      0    stevel 	mov	%g4, %o1
   1195      0    stevel 	mov	%g3, %o0
   1196      0    stevel 	retry
   1197      0    stevel 	SET_SIZE(vtag_flushall_tl1)
   1198      0    stevel 
   1199      0    stevel /*
   1200      0    stevel  * flush_instr_mem:
   1201      0    stevel  *	Flush a portion of the I-$ starting at vaddr
   1202      0    stevel  * 	%o0 vaddr
   1203      0    stevel  *	%o1 bytes to be flushed
   1204      0    stevel  */
   1205      0    stevel 
   1206      0    stevel 	ENTRY(flush_instr_mem)
   1207      0    stevel 	membar	#StoreStore				! Ensure the stores
   1208      0    stevel 							! are globally visible
   1209      0    stevel 1:
   1210      0    stevel 	flush	%o0
   1211      0    stevel 	subcc	%o1, ICACHE_FLUSHSZ, %o1		! bytes = bytes-0x20
   1212      0    stevel 	bgu,pt	%ncc, 1b
   1213   2241      huah 	  add	%o0, ICACHE_FLUSHSZ, %o0		! vaddr = vaddr+0x20
   1214      0    stevel 
   1215      0    stevel 	retl
   1216   2241      huah 	  nop
   1217      0    stevel 	SET_SIZE(flush_instr_mem)
   1218      0    stevel 
   1219      0    stevel #endif /* !lint */
   1220   1614  jb145095 
   1221   7718     Jason #if !defined(CUSTOM_FPZERO)
   1222   7718     Jason 
   1223   1614  jb145095 /*
   1224   1614  jb145095  * fp_zero() - clear all fp data registers and the fsr
   1225   1614  jb145095  */
   1226   1614  jb145095 
   1227   1614  jb145095 #if defined(lint) || defined(__lint)
   1228   1614  jb145095 
   1229   1614  jb145095 void
   1230   1614  jb145095 fp_zero(void)
   1231   1614  jb145095 {}
   1232   1614  jb145095 
   1233   1614  jb145095 #else	/* lint */
   1234   1614  jb145095 
   1235   1614  jb145095 .global	fp_zero_zero
   1236   1614  jb145095 .align 8
   1237   1614  jb145095 fp_zero_zero:
   1238   1614  jb145095 	.xword	0
   1239   1614  jb145095 
   1240   1614  jb145095 	ENTRY_NP(fp_zero)
   1241   1614  jb145095 	sethi	%hi(fp_zero_zero), %o0
   1242   7718     Jason 	ldx	[%o0 + %lo(fp_zero_zero)], %fsr
   1243   1614  jb145095 	ldd	[%o0 + %lo(fp_zero_zero)], %f0
   1244   1614  jb145095 	fmovd	%f0, %f2
   1245   1614  jb145095 	fmovd	%f0, %f4
   1246   1614  jb145095 	fmovd	%f0, %f6
   1247   1614  jb145095 	fmovd	%f0, %f8
   1248   1614  jb145095 	fmovd	%f0, %f10
   1249   1614  jb145095 	fmovd	%f0, %f12
   1250   1614  jb145095 	fmovd	%f0, %f14
   1251   1614  jb145095 	fmovd	%f0, %f16
   1252   1614  jb145095 	fmovd	%f0, %f18
   1253   1614  jb145095 	fmovd	%f0, %f20
   1254   1614  jb145095 	fmovd	%f0, %f22
   1255   1614  jb145095 	fmovd	%f0, %f24
   1256   1614  jb145095 	fmovd	%f0, %f26
   1257   1614  jb145095 	fmovd	%f0, %f28
   1258   1614  jb145095 	fmovd	%f0, %f30
   1259   1614  jb145095 	fmovd	%f0, %f32
   1260   1614  jb145095 	fmovd	%f0, %f34
   1261   1614  jb145095 	fmovd	%f0, %f36
   1262   1614  jb145095 	fmovd	%f0, %f38
   1263   1614  jb145095 	fmovd	%f0, %f40
   1264   1614  jb145095 	fmovd	%f0, %f42
   1265   1614  jb145095 	fmovd	%f0, %f44
   1266   1614  jb145095 	fmovd	%f0, %f46
   1267   1614  jb145095 	fmovd	%f0, %f48
   1268   1614  jb145095 	fmovd	%f0, %f50
   1269   1614  jb145095 	fmovd	%f0, %f52
   1270   1614  jb145095 	fmovd	%f0, %f54
   1271   1614  jb145095 	fmovd	%f0, %f56
   1272   1614  jb145095 	fmovd	%f0, %f58
   1273   1614  jb145095 	fmovd	%f0, %f60
   1274   1614  jb145095 	retl
   1275   1614  jb145095 	fmovd	%f0, %f62
   1276   1614  jb145095 	SET_SIZE(fp_zero)
   1277   1614  jb145095 
   1278   1614  jb145095 #endif	/* lint */
   1279   7718     Jason #endif  /* CUSTOM_FPZERO */
   1280