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  1772  jl139090  * Common Development and Distribution License (the "License").
      6  1772  jl139090  * 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	/* !lint */
     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     0    stevel /*
     46     0    stevel  * Override GET_NATIVE_TIME for the cpu module code.  This is not
     47     0    stevel  * guaranteed to be exactly one instruction, be careful of using
     48     0    stevel  * the macro in delay slots.
     49     0    stevel  *
     50     0    stevel  * Do not use any instruction that modifies condition codes as the
     51     0    stevel  * caller may depend on these to remain unchanged across the macro.
     52     0    stevel  */
     53  1772  jl139090 #if defined(CHEETAH) || defined(OLYMPUS_C)
     54     0    stevel 
     55     0    stevel #define	GET_NATIVE_TIME(out, scr1, scr2) \
     56     0    stevel 	rd	STICK, out
     57     0    stevel #define	DELTA_NATIVE_TIME(delta, reg, scr1, scr2, scr3) \
     58     0    stevel 	rd	STICK, reg;		\
     59     0    stevel 	add	reg, delta, reg;	\
     60     0    stevel 	wr	reg, STICK
     61     0    stevel #define	RD_TICKCMPR(out, scr)		\
     62     0    stevel 	rd	STICK_COMPARE, out
     63     0    stevel #define	WR_TICKCMPR(in, scr1, scr2, label) \
     64     0    stevel 	wr	in, STICK_COMPARE
     65     0    stevel 
     66     0    stevel #elif defined(HUMMINGBIRD)
     67     0    stevel #include <sys/spitregs.h>
     68     0    stevel 
     69     0    stevel /*
     70     0    stevel  * the current hummingbird version of %stick and %stick_cmp
     71     0    stevel  * were both implemented as (2) 32-bit locations in ASI_IO space;
     72     0    stevel  * the hdwr should support atomic r/w; meanwhile: ugly alert! ...
     73     0    stevel  *
     74     0    stevel  * 64-bit opcodes are required, but move only 32-bits:
     75     0    stevel  *
     76     0    stevel  * ldxa [phys]ASI_IO, %dst 	reads  the low 32-bits from phys into %dst
     77     0    stevel  * stxa %src, [phys]ASI_IO 	writes the low 32-bits from %src into phys
     78     0    stevel  *
     79     0    stevel  * reg equivalent		[phys]ASI_IO
     80     0    stevel  * ------------------		---------------
     81     0    stevel  * %stick_cmp  low-32		0x1FE.0000.F060
     82     0    stevel  * %stick_cmp high-32		0x1FE.0000.F068
     83     0    stevel  * %stick      low-32		0x1FE.0000.F070
     84     0    stevel  * %stick     high-32		0x1FE.0000.F078
     85     0    stevel  */
     86     0    stevel #define	HSTC_LOW	0x60			/* stick_cmp low  32-bits */
     87     0    stevel #define	HSTC_HIGH	0x68			/* stick_cmp high 32-bits */
     88     0    stevel #define	HST_LOW		0x70			/* stick low  32-bits */
     89     0    stevel #define	HST_HIGH	0x78			/* stick high 32-bits */
     90     0    stevel #define	HST_DIFF	0x08			/* low<-->high diff */
     91     0    stevel 
     92     0    stevel /*
     93     0    stevel  * Any change in the number of instructions in SETL41()
     94     0    stevel  * will affect SETL41_OFF
     95     0    stevel  */
     96     0    stevel #define	SETL41(reg, byte) \
     97     0    stevel 	sethi	%hi(0x1FE00000), reg;		/* 0000.0000.1FE0.0000 */ \
     98     0    stevel 	or	reg, 0xF, reg;			/* 0000.0000.1FE0.000F */ \
     99     0    stevel 	sllx	reg, 12, reg;			/* 0000.01FE.0000.F000 */ \
    100     0    stevel 	or	reg, byte, reg;			/* 0000.01FE.0000.F0xx */
    101     0    stevel 
    102     0    stevel /*
    103     0    stevel  * SETL41_OFF is used to calulate the relative PC value when a
    104     0    stevel  * branch instruction needs to go over SETL41() macro
    105     0    stevel  */
    106     0    stevel #define SETL41_OFF  16
    107     0    stevel 
    108     0    stevel /*
    109     0    stevel  * reading stick requires 2 loads, and there could be an intervening
    110     0    stevel  * low-to-high 32-bit rollover resulting in a return value that is
    111     0    stevel  * off by about (2 ^ 32); this rare case is prevented by re-reading
    112     0    stevel  * the low-32 bits after the high-32 and verifying the "after" value
    113     0    stevel  * is >= the "before" value; if not, increment the high-32 value.
    114     0    stevel  *
    115     0    stevel  * this method is limited to 1 rollover, and based on the fixed
    116     0    stevel  * stick-frequency (5555555), requires the loads to complete within
    117     0    stevel  * 773 seconds; incrementing the high-32 value will not overflow for
    118     0    stevel  * about 52644 years.
    119     0    stevel  *
    120     0    stevel  * writing stick requires 2 stores; if the old/new low-32 value is
    121     0    stevel  * near 0xffffffff, there could be another rollover (also rare).
    122     0    stevel  * to prevent this, we first write a 0 to the low-32, then write
    123     0    stevel  * new values to the high-32 then the low-32.
    124     0    stevel  *
    125     0    stevel  * When we detect a carry in the lower %stick register, we need to
    126     0    stevel  * read HST_HIGH again. However at the point where we detect this,
    127     0    stevel  * we need to rebuild the register address HST_HIGH.This involves more
    128     0    stevel  * than one instructions and a branch is unavoidable. However, most of
    129     0    stevel  * the time, there is no carry. So we take the penalty of a branch
    130     0    stevel  * instruction only when there is carry (less frequent).
    131     0    stevel  *
    132     0    stevel  * For GET_NATIVE_TIME(), we start afresh and branch to SETL41().
    133     0    stevel  * For DELTA_NATIVE_TIME(), we branch to just after SETL41() since
    134     0    stevel  * addr already points to HST_LOW.
    135     0    stevel  *
    136     0    stevel  * NOTE: this method requires disabling interrupts before using
    137     0    stevel  * DELTA_NATIVE_TIME.
    138     0    stevel  */
    139     0    stevel #define	GET_NATIVE_TIME(out, scr, tmp)	\
    140     0    stevel 	SETL41(scr, HST_LOW);		\
    141     0    stevel 	ldxa	[scr]ASI_IO, tmp;	\
    142     0    stevel 	inc	HST_DIFF, scr;		\
    143     0    stevel 	ldxa	[scr]ASI_IO, out;	\
    144     0    stevel 	dec	HST_DIFF, scr;		\
    145     0    stevel 	ldxa	[scr]ASI_IO, scr;	\
    146     0    stevel 	sub	scr, tmp, tmp;		\
    147     0    stevel 	brlz,pn tmp, .-(SETL41_OFF+24); \
    148     0    stevel 	sllx	out, 32, out;		\
    149     0    stevel 	or	out, scr, out
    150     0    stevel #define	DELTA_NATIVE_TIME(delta, addr, high, low, tmp) \
    151     0    stevel 	SETL41(addr, HST_LOW);		\
    152     0    stevel 	ldxa	[addr]ASI_IO, tmp;	\
    153     0    stevel 	inc	HST_DIFF, addr;		\
    154     0    stevel 	ldxa	[addr]ASI_IO, high;	\
    155     0    stevel 	dec	HST_DIFF, addr;		\
    156     0    stevel 	ldxa	[addr]ASI_IO, low;	\
    157     0    stevel 	sub	low, tmp, tmp;		\
    158     0    stevel 	brlz,pn tmp, .-24;		\
    159     0    stevel 	sllx	high, 32, high;		\
    160     0    stevel 	or	high, low, high;	\
    161     0    stevel 	add	high, delta, high;	\
    162     0    stevel 	srl	high, 0, low;		\
    163     0    stevel 	srlx	high, 32, high;		\
    164     0    stevel 	stxa	%g0, [addr]ASI_IO;	\
    165     0    stevel 	inc	HST_DIFF, addr;		\
    166     0    stevel 	stxa	high, [addr]ASI_IO;	\
    167     0    stevel 	dec	HST_DIFF, addr;		\
    168     0    stevel 	stxa	low, [addr]ASI_IO
    169     0    stevel #define RD_TICKCMPR(out, scr)		\
    170     0    stevel 	SETL41(scr, HSTC_LOW);		\
    171     0    stevel 	ldxa	[scr]ASI_IO, out;	\
    172     0    stevel 	inc	HST_DIFF, scr;		\
    173     0    stevel 	ldxa	[scr]ASI_IO, scr;	\
    174     0    stevel 	sllx	scr, 32, scr;		\
    175     0    stevel 	or	scr, out, out
    176     0    stevel #define WR_TICKCMPR(in, scra, scrd, label) \
    177     0    stevel 	SETL41(scra, HSTC_HIGH);	\
    178     0    stevel 	srlx	in, 32, scrd;		\
    179     0    stevel 	stxa	scrd, [scra]ASI_IO;	\
    180     0    stevel 	dec	HST_DIFF, scra;		\
    181     0    stevel 	stxa	in, [scra]ASI_IO
    182     0    stevel 
    183     0    stevel #else	/* !CHEETAH && !HUMMINGBIRD */
    184     0    stevel 
    185     0    stevel #define	GET_NATIVE_TIME(out, scr1, scr2) \
    186     0    stevel 	rdpr	%tick, out
    187     0    stevel #define	DELTA_NATIVE_TIME(delta, reg, scr1, scr2, scr3) \
    188     0    stevel 	rdpr	%tick, reg;		\
    189     0    stevel 	add	reg, delta, reg;	\
    190     0    stevel 	wrpr	reg, %tick
    191     0    stevel #define	RD_TICKCMPR(out, scr)		\
    192     0    stevel 	rd	TICK_COMPARE, out
    193     0    stevel #ifdef BB_ERRATA_1 /* writes to TICK_COMPARE may fail */
    194     0    stevel /*
    195     0    stevel  * Writes to the TICK_COMPARE register sometimes fail on blackbird modules.
    196     0    stevel  * The failure occurs only when the following instruction decodes to wr or
    197     0    stevel  * wrpr.  The workaround is to immediately follow writes to TICK_COMPARE
    198     0    stevel  * with a read, thus stalling the pipe and keeping following instructions
    199     0    stevel  * from causing data corruption.  Aligning to a quadword will ensure these
    200     0    stevel  * two instructions are not split due to i$ misses.
    201     0    stevel  */
    202     0    stevel #define WR_TICKCMPR(cmpr,scr1,scr2,label)	\
    203     0    stevel 	ba,a	.bb_errata_1.label		;\
    204     0    stevel 	.align	64				;\
    205     0    stevel .bb_errata_1.label:				;\
    206     0    stevel 	wr	cmpr, TICK_COMPARE		;\
    207     0    stevel 	rd	TICK_COMPARE, %g0
    208     0    stevel #else	/* BB_ERRATA_1 */
    209     0    stevel #define	WR_TICKCMPR(in,scr1,scr2,label)		\
    210     0    stevel 	wr	in, TICK_COMPARE
    211     0    stevel #endif	/* BB_ERRATA_1 */
    212     0    stevel 
    213     0    stevel #endif	/* !CHEETAH && !HUMMINGBIRD */
    214     0    stevel 
    215     0    stevel #include <sys/clock.h>
    216     0    stevel 
    217     0    stevel #if defined(lint)
    218     0    stevel #include <sys/types.h>
    219     0    stevel #include <sys/scb.h>
    220     0    stevel #include <sys/systm.h>
    221     0    stevel #include <sys/regset.h>
    222     0    stevel #include <sys/sunddi.h>
    223     0    stevel #include <sys/lockstat.h>
    224     0    stevel #endif	/* lint */
    225     0    stevel 
    226     0    stevel 
    227     0    stevel #include <sys/asm_linkage.h>
    228     0    stevel #include <sys/privregs.h>
    229     0    stevel #include <sys/machparam.h>	/* To get SYSBASE and PAGESIZE */
    230     0    stevel #include <sys/machthread.h>
    231     0    stevel #include <sys/clock.h>
    232     0    stevel #include <sys/intreg.h>
    233     0    stevel #include <sys/psr_compat.h>
    234     0    stevel #include <sys/isa_defs.h>
    235     0    stevel #include <sys/dditypes.h>
    236     0    stevel #include <sys/intr.h>
    237     0    stevel 
    238     0    stevel #if !defined(lint)
    239     0    stevel #include "assym.h"
    240     0    stevel #endif	/* !lint */
    241     0    stevel 
    242     0    stevel #if defined(lint)
    243     0    stevel 
    244     0    stevel uint_t
    245     0    stevel get_impl(void)
    246     0    stevel { return (0); }
    247     0    stevel 
    248     0    stevel #else	/* lint */
    249     0    stevel 
    250     0    stevel 	ENTRY(get_impl)
    251     0    stevel 	GET_CPU_IMPL(%o0)
    252     0    stevel 	retl
    253     0    stevel 	nop
    254     0    stevel 	SET_SIZE(get_impl)
    255     0    stevel 
    256     0    stevel #endif	/* lint */
    257     0    stevel 
    258     0    stevel #if defined(lint)
    259     0    stevel /*
    260     0    stevel  * Softint generated when counter field of tick reg matches value field
    261     0    stevel  * of tick_cmpr reg
    262     0    stevel  */
    263     0    stevel /*ARGSUSED*/
    264     0    stevel void
    265     0    stevel tickcmpr_set(uint64_t clock_cycles)
    266     0    stevel {}
    267     0    stevel 
    268     0    stevel #else	/* lint */
    269     0    stevel 
    270     0    stevel 	ENTRY_NP(tickcmpr_set)
    271     0    stevel 	! get 64-bit clock_cycles interval
    272     0    stevel 	mov	%o0, %o2
    273     0    stevel 	mov	8, %o3			! A reasonable initial step size
    274     0    stevel 1:
    275     0    stevel 	WR_TICKCMPR(%o2,%o4,%o5,__LINE__)	! Write to TICK_CMPR
    276     0    stevel 
    277     0    stevel 	GET_NATIVE_TIME(%o0, %o4, %o5)	! Read %tick to confirm the
    278     0    stevel 	sllx	%o0, 1, %o0		!   value we wrote was in the future.
    279     0    stevel 	srlx	%o0, 1, %o0
    280     0    stevel 
    281     0    stevel 	cmp	%o2, %o0		! If the value we wrote was in the
    282     0    stevel 	bg,pt	%xcc, 2f		!   future, then blow out of here.
    283     0    stevel 	sllx	%o3, 1, %o3		! If not, then double our step size,
    284     0    stevel 	ba,pt	%xcc, 1b		!   and take another lap.
    285     0    stevel 	add	%o0, %o3, %o2		!
    286     0    stevel 2:
    287     0    stevel 	retl
    288     0    stevel 	nop
    289     0    stevel 	SET_SIZE(tickcmpr_set)
    290     0    stevel 
    291     0    stevel #endif	/* lint */
    292     0    stevel 
    293     0    stevel #if defined(lint)
    294     0    stevel 
    295     0    stevel void
    296     0    stevel tickcmpr_disable(void)
    297     0    stevel {}
    298     0    stevel 
    299     0    stevel #else	/* lint */
    300     0    stevel 
    301     0    stevel 	ENTRY_NP(tickcmpr_disable)
    302     0    stevel 	mov	1, %g1
    303     0    stevel 	sllx	%g1, TICKINT_DIS_SHFT, %o0
    304     0    stevel 	WR_TICKCMPR(%o0,%o4,%o5,__LINE__)	! Write to TICK_CMPR
    305     0    stevel 	retl
    306     0    stevel 	nop
    307     0    stevel 	SET_SIZE(tickcmpr_disable)
    308     0    stevel 
    309     0    stevel #endif	/* lint */
    310     0    stevel 
    311     0    stevel #if defined(lint)
    312     0    stevel 
    313     0    stevel /*
    314     0    stevel  * tick_write_delta() increments %tick by the specified delta.  This should
    315     0    stevel  * only be called after a CPR event to assure that gethrtime() continues to
    316     0    stevel  * increase monotonically.  Obviously, writing %tick needs to de done very
    317     0    stevel  * carefully to avoid introducing unnecessary %tick skew across CPUs.  For
    318     0    stevel  * this reason, we make sure we're i-cache hot before actually writing to
    319     0    stevel  * %tick.
    320     0    stevel  */
    321     0    stevel /*ARGSUSED*/
    322     0    stevel void
    323     0    stevel tick_write_delta(uint64_t delta)
    324     0    stevel {}
    325     0    stevel 
    326     0    stevel #else	/* lint */
    327     0    stevel 
    328     0    stevel #ifdef DEBUG
    329     0    stevel 	.seg	".text"
    330     0    stevel tick_write_panic:
    331     0    stevel 	.asciz	"tick_write_delta: interrupts already disabled on entry"
    332     0    stevel #endif	/* DEBUG */
    333     0    stevel 
    334     0    stevel 	ENTRY_NP(tick_write_delta)
    335     0    stevel 	rdpr	%pstate, %g1
    336     0    stevel #ifdef DEBUG
    337     0    stevel 	andcc	%g1, PSTATE_IE, %g0	! If DEBUG, check that interrupts
    338     0    stevel 	bnz	0f			! aren't already disabled.
    339     0    stevel 	sethi	%hi(tick_write_panic), %o1
    340     0    stevel         save    %sp, -SA(MINFRAME), %sp ! get a new window to preserve caller
    341     0    stevel 	call	panic
    342     0    stevel 	or	%i1, %lo(tick_write_panic), %o0
    343     0    stevel #endif	/* DEBUG */
    344     0    stevel 0:	wrpr	%g1, PSTATE_IE, %pstate	! Disable interrupts
    345     0    stevel 	mov	%o0, %o2
    346     0    stevel 	ba	0f			! Branch to cache line-aligned instr.
    347     0    stevel 	nop
    348     0    stevel 	.align	16
    349     0    stevel 0:	nop				! The next 3 instructions are now hot.
    350     0    stevel 	DELTA_NATIVE_TIME(%o2, %o3, %o4, %o5, %g2)	! read/inc/write %tick
    351     0    stevel 
    352     0    stevel 	retl				! Return
    353     0    stevel 	wrpr	%g0, %g1, %pstate	!     delay: Re-enable interrupts
    354     0    stevel #endif	/* lint */
    355     0    stevel 
    356     0    stevel #if defined(lint)
    357     0    stevel /*
    358     0    stevel  *  return 1 if disabled
    359     0    stevel  */
    360     0    stevel 
    361     0    stevel int
    362     0    stevel tickcmpr_disabled(void)
    363     0    stevel { return (0); }
    364     0    stevel 
    365     0    stevel #else	/* lint */
    366     0    stevel 
    367     0    stevel 	ENTRY_NP(tickcmpr_disabled)
    368     0    stevel 	RD_TICKCMPR(%g1, %o0)
    369     0    stevel 	retl
    370     0    stevel 	srlx	%g1, TICKINT_DIS_SHFT, %o0
    371     0    stevel 	SET_SIZE(tickcmpr_disabled)
    372     0    stevel 
    373     0    stevel #endif	/* lint */
    374     0    stevel 
    375     0    stevel /*
    376     0    stevel  * Get current tick
    377     0    stevel  */
    378     0    stevel #if defined(lint)
    379     0    stevel 
    380     0    stevel u_longlong_t
    381     0    stevel gettick(void)
    382     0    stevel { return (0); }
    383     0    stevel 
    384     0    stevel #else	/* lint */
    385     0    stevel 
    386     0    stevel 	ENTRY(gettick)
    387     0    stevel 	GET_NATIVE_TIME(%o0, %o2, %o3)
    388     0    stevel 	retl
    389     0    stevel 	nop
    390     0    stevel 	SET_SIZE(gettick)
    391     0    stevel 
    392     0    stevel #endif	/* lint */
    393     0    stevel 
    394     0    stevel 
    395     0    stevel /*
    396     0    stevel  * Return the counter portion of the tick register.
    397     0    stevel  */
    398     0    stevel 
    399     0    stevel #if defined(lint)
    400     0    stevel 
    401     0    stevel uint64_t
    402     0    stevel gettick_counter(void)
    403     0    stevel { return(0); }
    404     0    stevel 
    405     0    stevel #else	/* lint */
    406     0    stevel 
    407     0    stevel 	ENTRY_NP(gettick_counter)
    408     0    stevel 	rdpr	%tick, %o0
    409     0    stevel 	sllx	%o0, 1, %o0
    410     0    stevel 	retl
    411     0    stevel 	srlx	%o0, 1, %o0		! shake off npt bit
    412     0    stevel 	SET_SIZE(gettick_counter)
    413     0    stevel #endif	/* lint */
    414     0    stevel 
    415     0    stevel /*
    416     0    stevel  * Provide a C callable interface to the trap that reads the hi-res timer.
    417     0    stevel  * Returns 64-bit nanosecond timestamp in %o0 and %o1.
    418     0    stevel  */
    419     0    stevel 
    420     0    stevel #if defined(lint)
    421     0    stevel 
    422     0    stevel hrtime_t
    423     0    stevel gethrtime(void)
    424     0    stevel {
    425     0    stevel 	return ((hrtime_t)0);
    426     0    stevel }
    427     0    stevel 
    428     0    stevel hrtime_t
    429     0    stevel gethrtime_unscaled(void)
    430     0    stevel {
    431     0    stevel 	return ((hrtime_t)0);
    432     0    stevel }
    433     0    stevel 
    434     0    stevel hrtime_t
    435     0    stevel gethrtime_max(void)
    436     0    stevel {
    437     0    stevel 	return ((hrtime_t)0);
    438     0    stevel }
    439     0    stevel 
    440     0    stevel void
    441     0    stevel scalehrtime(hrtime_t *hrt)
    442     0    stevel {
    443     0    stevel 	*hrt = 0;
    444     0    stevel }
    445     0    stevel 
    446     0    stevel void
    447     0    stevel gethrestime(timespec_t *tp)
    448     0    stevel {
    449     0    stevel 	tp->tv_sec = 0;
    450     0    stevel 	tp->tv_nsec = 0;
    451     0    stevel }
    452     0    stevel 
    453     0    stevel time_t
    454     0    stevel gethrestime_sec(void)
    455     0    stevel {
    456     0    stevel 	return (0);
    457     0    stevel }
    458     0    stevel 
    459     0    stevel void
    460     0    stevel gethrestime_lasttick(timespec_t *tp)
    461     0    stevel {
    462     0    stevel 	tp->tv_sec = 0;
    463     0    stevel 	tp->tv_nsec = 0;
    464     0    stevel }
    465     0    stevel 
    466     0    stevel /*ARGSUSED*/
    467     0    stevel void
    468     0    stevel hres_tick(void)
    469     0    stevel {
    470     0    stevel }
    471     0    stevel 
    472     0    stevel void
    473     0    stevel panic_hres_tick(void)
    474     0    stevel {
    475     0    stevel }
    476     0    stevel 
    477     0    stevel #else	/* lint */
    478     0    stevel 
    479     0    stevel 	ENTRY_NP(gethrtime)
    480     0    stevel 	GET_HRTIME(%g1, %o0, %o1, %o2, %o3, %o4, %o5, %g2)
    481     0    stevel 							! %g1 = hrtime
    482     0    stevel 	retl
    483     0    stevel 	mov	%g1, %o0
    484     0    stevel 	SET_SIZE(gethrtime)
    485     0    stevel 
    486     0    stevel 	ENTRY_NP(gethrtime_unscaled)
    487     0    stevel 	GET_NATIVE_TIME(%g1, %o2, %o3)			! %g1 = native time
    488     0    stevel 	retl
    489     0    stevel 	mov	%g1, %o0
    490     0    stevel 	SET_SIZE(gethrtime_unscaled)
    491     0    stevel 
    492     0    stevel 	ENTRY_NP(gethrtime_waitfree)
    493     0    stevel 	ALTENTRY(dtrace_gethrtime)
    494     0    stevel 	GET_NATIVE_TIME(%g1, %o2, %o3)			! %g1 = native time
    495     0    stevel 	NATIVE_TIME_TO_NSEC(%g1, %o2, %o3)
    496     0    stevel 	retl
    497     0    stevel 	mov	%g1, %o0
    498     0    stevel 	SET_SIZE(dtrace_gethrtime)
    499     0    stevel 	SET_SIZE(gethrtime_waitfree)
    500     0    stevel 
    501     0    stevel 	ENTRY(gethrtime_max)
    502     0    stevel 	NATIVE_TIME_MAX(%g1)
    503     0    stevel 	NATIVE_TIME_TO_NSEC(%g1, %o0, %o1)
    504     0    stevel 
    505     0    stevel 	! hrtime_t's are signed, max hrtime_t must be positive
    506     0    stevel 	mov	-1, %o2
    507     0    stevel 	brlz,a	%g1, 1f
    508     0    stevel 	srlx	%o2, 1, %g1
    509     0    stevel 1:
    510     0    stevel 	retl
    511     0    stevel 	mov	%g1, %o0
    512     0    stevel 	SET_SIZE(gethrtime_max)
    513     0    stevel 
    514     0    stevel 	ENTRY(scalehrtime)
    515     0    stevel 	ldx	[%o0], %o1
    516     0    stevel 	NATIVE_TIME_TO_NSEC(%o1, %o2, %o3)
    517     0    stevel 	retl
    518     0    stevel 	stx	%o1, [%o0]
    519     0    stevel 	SET_SIZE(scalehrtime)
    520     0    stevel 
    521     0    stevel /*
    522     0    stevel  * Fast trap to return a timestamp, uses trap window, leaves traps
    523     0    stevel  * disabled.  Returns a 64-bit nanosecond timestamp in %o0 and %o1.
    524     0    stevel  *
    525     0    stevel  * This is the handler for the ST_GETHRTIME trap.
    526     0    stevel  */
    527     0    stevel 
    528     0    stevel 	ENTRY_NP(get_timestamp)
    529     0    stevel 	GET_HRTIME(%g1, %g2, %g3, %g4, %g5, %o0, %o1, %o2)	! %g1 = hrtime
    530     0    stevel 	srlx	%g1, 32, %o0				! %o0 = hi32(%g1)
    531     0    stevel 	srl	%g1, 0, %o1				! %o1 = lo32(%g1)
    532     0    stevel 	FAST_TRAP_DONE
    533     0    stevel 	SET_SIZE(get_timestamp)
    534     0    stevel 
    535     0    stevel /*
    536     0    stevel  * Macro to convert GET_HRESTIME() bits into a timestamp.
    537     0    stevel  *
    538     0    stevel  * We use two separate macros so that the platform-dependent GET_HRESTIME()
    539     0    stevel  * can be as small as possible; CONV_HRESTIME() implements the generic part.
    540     0    stevel  */
    541     0    stevel #define	CONV_HRESTIME(hrestsec, hrestnsec, adj, nslt, nano) \
    542     0    stevel 	brz,pt	adj, 3f;		/* no adjustments, it's easy */	\
    543     0    stevel 	add	hrestnsec, nslt, hrestnsec; /* hrest.tv_nsec += nslt */	\
    544     0    stevel 	brlz,pn	adj, 2f;		/* if hrestime_adj negative */	\
    545  2399       cth 	srlx	nslt, ADJ_SHIFT, nslt;	/* delay: nslt >>= 4 */		\
    546     0    stevel 	subcc	adj, nslt, %g0;		/* hrestime_adj - nslt/16 */	\
    547     0    stevel 	movg	%xcc, nslt, adj;	/* adj by min(adj, nslt/16) */	\
    548     0    stevel 	ba	3f;			/* go convert to sec/nsec */	\
    549     0    stevel 	add	hrestnsec, adj, hrestnsec; /* delay: apply adjustment */ \
    550     0    stevel 2:	addcc	adj, nslt, %g0;		/* hrestime_adj + nslt/16 */	\
    551     0    stevel 	bge,a,pt %xcc, 3f;		/* is adj less negative? */	\
    552     0    stevel 	add	hrestnsec, adj, hrestnsec; /* yes: hrest.nsec += adj */	\
    553     0    stevel 	sub	hrestnsec, nslt, hrestnsec; /* no: hrest.nsec -= nslt/16 */ \
    554     0    stevel 3:	cmp	hrestnsec, nano;	/* more than a billion? */	\
    555     0    stevel 	bl,pt	%xcc, 4f;		/* if not, we're done */	\
    556     0    stevel 	nop;				/* delay: do nothing :( */	\
    557     0    stevel 	add	hrestsec, 1, hrestsec;	/* hrest.tv_sec++; */		\
    558     0    stevel 	sub	hrestnsec, nano, hrestnsec; /* hrest.tv_nsec -= NANOSEC; */ \
    559  2399       cth 	ba,a	3b;			/* check >= billion again */	\
    560     0    stevel 4:
    561     0    stevel 
    562     0    stevel 	ENTRY_NP(gethrestime)
    563     0    stevel 	GET_HRESTIME(%o1, %o2, %o3, %o4, %o5, %g1, %g2, %g3, %g4)
    564     0    stevel 	CONV_HRESTIME(%o1, %o2, %o3, %o4, %o5)
    565     0    stevel 	stn	%o1, [%o0]
    566     0    stevel 	retl
    567     0    stevel 	stn	%o2, [%o0 + CLONGSIZE]
    568     0    stevel 	SET_SIZE(gethrestime)
    569     0    stevel 
    570     0    stevel /*
    571     0    stevel  * Similar to gethrestime(), but gethrestime_sec() returns current hrestime
    572     0    stevel  * seconds.
    573     0    stevel  */
    574     0    stevel 	ENTRY_NP(gethrestime_sec)
    575     0    stevel 	GET_HRESTIME(%o0, %o2, %o3, %o4, %o5, %g1, %g2, %g3, %g4)
    576     0    stevel 	CONV_HRESTIME(%o0, %o2, %o3, %o4, %o5)
    577     0    stevel 	retl					! %o0 current hrestime seconds
    578     0    stevel 	nop
    579     0    stevel 	SET_SIZE(gethrestime_sec)
    580     0    stevel 
    581     0    stevel /*
    582     0    stevel  * Returns the hrestime on the last tick.  This is simpler than gethrestime()
    583     0    stevel  * and gethrestime_sec():  no conversion is required.  gethrestime_lasttick()
    584     0    stevel  * follows the same locking algorithm as GET_HRESTIME and GET_HRTIME,
    585     0    stevel  * outlined in detail in clock.h.  (Unlike GET_HRESTIME/GET_HRTIME, we don't
    586     0    stevel  * rely on load dependencies to effect the membar #LoadLoad, instead declaring
    587     0    stevel  * it explicitly.)
    588     0    stevel  */
    589     0    stevel 	ENTRY_NP(gethrestime_lasttick)
    590     0    stevel 	sethi	%hi(hres_lock), %o1
    591     0    stevel 0:
    592     0    stevel 	lduw	[%o1 + %lo(hres_lock)], %o2	! Load lock value
    593     0    stevel 	membar	#LoadLoad			! Load of lock must complete
    594     0    stevel 	andn	%o2, 1, %o2			! Mask off lowest bit
    595     0    stevel 	ldn	[%o1 + %lo(hrestime)], %g1	! Seconds.
    596     0    stevel 	add	%o1, %lo(hrestime), %o4
    597     0    stevel 	ldn	[%o4 + CLONGSIZE], %g2		! Nanoseconds.
    598     0    stevel 	membar	#LoadLoad			! All loads must complete
    599     0    stevel 	lduw	[%o1 + %lo(hres_lock)], %o3	! Reload lock value
    600     0    stevel 	cmp	%o3, %o2			! If lock is locked or has
    601     0    stevel 	bne	0b				!   changed, retry.
    602     0    stevel 	stn	%g1, [%o0]			! Delay: store seconds
    603     0    stevel 	retl
    604     0    stevel 	stn	%g2, [%o0 + CLONGSIZE]		! Delay: store nanoseconds
    605     0    stevel 	SET_SIZE(gethrestime_lasttick)
    606     0    stevel 
    607     0    stevel /*
    608     0    stevel  * Fast trap for gettimeofday().  Returns a timestruc_t in %o0 and %o1.
    609     0    stevel  *
    610     0    stevel  * This is the handler for the ST_GETHRESTIME trap.
    611     0    stevel  */
    612     0    stevel 
    613     0    stevel 	ENTRY_NP(get_hrestime)
    614     0    stevel 	GET_HRESTIME(%o0, %o1, %g1, %g2, %g3, %g4, %g5, %o2, %o3)
    615     0    stevel 	CONV_HRESTIME(%o0, %o1, %g1, %g2, %g3)
    616     0    stevel 	FAST_TRAP_DONE
    617     0    stevel 	SET_SIZE(get_hrestime)
    618     0    stevel 
    619     0    stevel /*
    620     0    stevel  * Fast trap to return lwp virtual time, uses trap window, leaves traps
    621     0    stevel  * disabled.  Returns a 64-bit number in %o0:%o1, which is the number
    622     0    stevel  * of nanoseconds consumed.
    623     0    stevel  *
    624     0    stevel  * This is the handler for the ST_GETHRVTIME trap.
    625     0    stevel  *
    626     0    stevel  * Register usage:
    627     0    stevel  *	%o0, %o1 = return lwp virtual time
    628     0    stevel  * 	%o2 = CPU/thread
    629     0    stevel  * 	%o3 = lwp
    630     0    stevel  * 	%g1 = scratch
    631     0    stevel  * 	%g5 = scratch
    632     0    stevel  */
    633     0    stevel 	ENTRY_NP(get_virtime)
    634     0    stevel 	GET_NATIVE_TIME(%g5, %g1, %g2)	! %g5 = native time in ticks
    635     0    stevel 	CPU_ADDR(%g2, %g3)			! CPU struct ptr to %g2
    636     0    stevel 	ldn	[%g2 + CPU_THREAD], %g2		! thread pointer to %g2
    637     0    stevel 	ldn	[%g2 + T_LWP], %g3		! lwp pointer to %g3
    638     0    stevel 
    639     0    stevel 	/*
    640     0    stevel 	 * Subtract start time of current microstate from time
    641     0    stevel 	 * of day to get increment for lwp virtual time.
    642     0    stevel 	 */
    643     0    stevel 	ldx	[%g3 + LWP_STATE_START], %g1	! ms_state_start
    644     0    stevel 	sub	%g5, %g1, %g5
    645     0    stevel 
    646     0    stevel 	/*
    647     0    stevel 	 * Add current value of ms_acct[LMS_USER]
    648     0    stevel 	 */
    649     0    stevel 	ldx	[%g3 + LWP_ACCT_USER], %g1	! ms_acct[LMS_USER]
    650     0    stevel 	add	%g5, %g1, %g5
    651     0    stevel 	NATIVE_TIME_TO_NSEC(%g5, %g1, %o0)
    652     0    stevel 
    653     0    stevel 	srl	%g5, 0, %o1			! %o1 = lo32(%g5)
    654     0    stevel 	srlx	%g5, 32, %o0			! %o0 = hi32(%g5)
    655     0    stevel 
    656     0    stevel 	FAST_TRAP_DONE
    657     0    stevel 	SET_SIZE(get_virtime)
    658     0    stevel 
    659     0    stevel 
    660     0    stevel 
    661     0    stevel 	.seg	".text"
    662     0    stevel hrtime_base_panic:
    663     0    stevel 	.asciz	"hrtime_base stepping back"
    664     0    stevel 
    665     0    stevel 
    666     0    stevel 	ENTRY_NP(hres_tick)
    667     0    stevel 	save	%sp, -SA(MINFRAME), %sp	! get a new window
    668     0    stevel 
    669     0    stevel 	sethi	%hi(hrestime), %l4
    670     0    stevel 	ldstub	[%l4 + %lo(hres_lock + HRES_LOCK_OFFSET)], %l5	! try locking
    671     0    stevel 7:	tst	%l5
    672     0    stevel 	bz,pt	%xcc, 8f			! if we got it, drive on
    673     0    stevel 	ld	[%l4 + %lo(nsec_scale)], %l5	! delay: %l5 = scaling factor
    674     0    stevel 	ldub	[%l4 + %lo(hres_lock + HRES_LOCK_OFFSET)], %l5
    675     0    stevel 9:	tst	%l5
    676     0    stevel 	bz,a,pn	%xcc, 7b
    677     0    stevel 	ldstub	[%l4 + %lo(hres_lock + HRES_LOCK_OFFSET)], %l5
    678     0    stevel 	ba,pt	%xcc, 9b
    679     0    stevel 	ldub	[%l4 + %lo(hres_lock + HRES_LOCK_OFFSET)], %l5
    680     0    stevel 8:
    681     0    stevel 	membar	#StoreLoad|#StoreStore
    682     0    stevel 
    683     0    stevel 	!
    684     0    stevel 	! update hres_last_tick.  %l5 has the scaling factor (nsec_scale).
    685     0    stevel 	!
    686     0    stevel 	ldx	[%l4 + %lo(hrtime_base)], %g1	! load current hrtime_base
    687     0    stevel 	GET_NATIVE_TIME(%l0, %l3, %l6)		! current native time
    688     0    stevel 	stx	%l0, [%l4 + %lo(hres_last_tick)]! prev = current
    689     0    stevel 	! convert native time to nsecs
    690     0    stevel 	NATIVE_TIME_TO_NSEC_SCALE(%l0, %l5, %l2, NSEC_SHIFT)
    691     0    stevel 
    692     0    stevel 	sub	%l0, %g1, %i1			! get accurate nsec delta
    693     0    stevel 
    694     0    stevel 	ldx	[%l4 + %lo(hrtime_base)], %l1
    695     0    stevel 	cmp	%l1, %l0
    696     0    stevel 	bg,pn	%xcc, 9f
    697     0    stevel 	nop
    698     0    stevel 
    699     0    stevel 	stx	%l0, [%l4 + %lo(hrtime_base)]	! update hrtime_base
    700     0    stevel 
    701     0    stevel 	!
    702     0    stevel 	! apply adjustment, if any
    703     0    stevel 	!
    704     0    stevel 	ldx	[%l4 + %lo(hrestime_adj)], %l0	! %l0 = hrestime_adj
    705     0    stevel 	brz	%l0, 2f
    706     0    stevel 						! hrestime_adj == 0 ?
    707     0    stevel 						! yes, skip adjustments
    708     0    stevel 	clr	%l5				! delay: set adj to zero
    709     0    stevel 	tst	%l0				! is hrestime_adj >= 0 ?
    710     0    stevel 	bge,pt	%xcc, 1f			! yes, go handle positive case
    711     0    stevel 	srl	%i1, ADJ_SHIFT, %l5		! delay: %l5 = adj
    712     0    stevel 
    713     0    stevel 	addcc	%l0, %l5, %g0			! hrestime_adj < -adj ?
    714     0    stevel 	bl,pt	%xcc, 2f			! yes, use current adj
    715     0    stevel 	neg	%l5				! delay: %l5 = -adj
    716     0    stevel 	ba,pt	%xcc, 2f
    717     0    stevel 	mov	%l0, %l5			! no, so set adj = hrestime_adj
    718     0    stevel 1:
    719     0    stevel 	subcc	%l0, %l5, %g0			! hrestime_adj < adj ?
    720     0    stevel 	bl,a,pt	%xcc, 2f			! yes, set adj = hrestime_adj
    721     0    stevel 	mov	%l0, %l5			! delay: adj = hrestime_adj
    722     0    stevel 2:
    723     0    stevel 	ldx	[%l4 + %lo(timedelta)], %l0	! %l0 = timedelta
    724     0    stevel 	sub	%l0, %l5, %l0			! timedelta -= adj
    725     0    stevel 
    726     0    stevel 	stx	%l0, [%l4 + %lo(timedelta)]	! store new timedelta
    727     0    stevel 	stx	%l0, [%l4 + %lo(hrestime_adj)]	! hrestime_adj = timedelta
    728     0    stevel 
    729     0    stevel 	or	%l4, %lo(hrestime), %l2
    730     0    stevel 	ldn	[%l2], %i2			! %i2:%i3 = hrestime sec:nsec
    731     0    stevel 	ldn	[%l2 + CLONGSIZE], %i3
    732     0    stevel 	add	%i3, %l5, %i3			! hrestime.nsec += adj
    733     0    stevel 	add	%i3, %i1, %i3			! hrestime.nsec += nslt
    734     0    stevel 
    735     0    stevel 	set	NANOSEC, %l5			! %l5 = NANOSEC
    736     0    stevel 	cmp	%i3, %l5
    737     0    stevel 	bl,pt	%xcc, 5f			! if hrestime.tv_nsec < NANOSEC
    738     0    stevel 	sethi	%hi(one_sec), %i1		! delay
    739     0    stevel 	add	%i2, 0x1, %i2			! hrestime.tv_sec++
    740     0    stevel 	sub	%i3, %l5, %i3			! hrestime.tv_nsec - NANOSEC
    741     0    stevel 	mov	0x1, %l5
    742     0    stevel 	st	%l5, [%i1 + %lo(one_sec)]
    743     0    stevel 5:
    744     0    stevel 	stn	%i2, [%l2]
    745     0    stevel 	stn	%i3, [%l2 + CLONGSIZE]		! store the new hrestime
    746     0    stevel 
    747     0    stevel 	membar	#StoreStore
    748     0    stevel 
    749     0    stevel 	ld	[%l4 + %lo(hres_lock)], %i1
    750     0    stevel 	inc	%i1				! release lock
    751     0    stevel 	st	%i1, [%l4 + %lo(hres_lock)]	! clear hres_lock
    752     0    stevel 
    753     0    stevel 	ret
    754     0    stevel 	restore
    755     0    stevel 
    756     0    stevel 9:
    757     0    stevel 	!
    758     0    stevel 	! release hres_lock
    759     0    stevel 	!
    760     0    stevel 	ld	[%l4 + %lo(hres_lock)], %i1
    761     0    stevel 	inc	%i1
    762     0    stevel 	st	%i1, [%l4 + %lo(hres_lock)]
    763     0    stevel 
    764     0    stevel 	sethi	%hi(hrtime_base_panic), %o0
    765     0    stevel 	call	panic
    766     0    stevel 	or	%o0, %lo(hrtime_base_panic), %o0
    767     0    stevel 
    768     0    stevel 	SET_SIZE(hres_tick)
    769     0    stevel 
    770     0    stevel #endif	/* lint */
    771     0    stevel 
    772     0    stevel #if !defined(lint) && !defined(__lint)
    773     0    stevel 
    774     0    stevel 	.seg	".text"
    775     0    stevel kstat_q_panic_msg:
    776     0    stevel 	.asciz	"kstat_q_exit: qlen == 0"
    777     0    stevel 
    778     0    stevel 	ENTRY(kstat_q_panic)
    779     0    stevel 	save	%sp, -SA(MINFRAME), %sp
    780     0    stevel 	sethi	%hi(kstat_q_panic_msg), %o0
    781     0    stevel 	call	panic
    782     0    stevel 	or	%o0, %lo(kstat_q_panic_msg), %o0
    783     0    stevel 	/*NOTREACHED*/
    784     0    stevel 	SET_SIZE(kstat_q_panic)
    785     0    stevel 
    786     0    stevel #define	BRZPN	brz,pn
    787     0    stevel #define	BRZPT	brz,pt
    788     0    stevel 
    789     0    stevel #define	KSTAT_Q_UPDATE(QOP, QBR, QZERO, QRETURN, QTYPE) \
    790     0    stevel 	ld	[%o0 + QTYPE/**/CNT], %o1;	/* %o1 = old qlen */	\
    791     0    stevel 	QOP	%o1, 1, %o2;			/* %o2 = new qlen */	\
    792     0    stevel 	QBR	%o1, QZERO;			/* done if qlen == 0 */	\
    793     0    stevel 	st	%o2, [%o0 + QTYPE/**/CNT];	/* delay: save qlen */	\
    794     0    stevel 	ldx	[%o0 + QTYPE/**/LASTUPDATE], %o3;			\
    795     0    stevel 	ldx	[%o0 + QTYPE/**/TIME], %o4;	/* %o4 = old time */	\
    796     0    stevel 	ldx	[%o0 + QTYPE/**/LENTIME], %o5;	/* %o5 = old lentime */	\
    797     0    stevel 	sub	%g1, %o3, %o2;			/* %o2 = time delta */	\
    798     0    stevel 	mulx	%o1, %o2, %o3;			/* %o3 = cur lentime */	\
    799     0    stevel 	add	%o4, %o2, %o4;			/* %o4 = new time */	\
    800     0    stevel 	add	%o5, %o3, %o5;			/* %o5 = new lentime */	\
    801     0    stevel 	stx	%o4, [%o0 + QTYPE/**/TIME];	/* save time */		\
    802     0    stevel 	stx	%o5, [%o0 + QTYPE/**/LENTIME];	/* save lentime */	\
    803     0    stevel QRETURN;								\
    804     0    stevel 	stx	%g1, [%o0 + QTYPE/**/LASTUPDATE]; /* lastupdate = now */
    805     0    stevel 
    806     0    stevel 	.align 16
    807     0    stevel 	ENTRY(kstat_waitq_enter)
    808     0    stevel 	GET_NATIVE_TIME(%g1, %g2, %g3)
    809     0    stevel 	KSTAT_Q_UPDATE(add, BRZPT, 1f, 1:retl, KSTAT_IO_W)
    810     0    stevel 	SET_SIZE(kstat_waitq_enter)
    811     0    stevel 
    812     0    stevel 	.align 16
    813     0    stevel 	ENTRY(kstat_waitq_exit)
    814     0    stevel 	GET_NATIVE_TIME(%g1, %g2, %g3)
    815     0    stevel 	KSTAT_Q_UPDATE(sub, BRZPN, kstat_q_panic, retl, KSTAT_IO_W)
    816     0    stevel 	SET_SIZE(kstat_waitq_exit)
    817     0    stevel 
    818     0    stevel 	.align 16
    819     0    stevel 	ENTRY(kstat_runq_enter)
    820     0    stevel 	GET_NATIVE_TIME(%g1, %g2, %g3)
    821     0    stevel 	KSTAT_Q_UPDATE(add, BRZPT, 1f, 1:retl, KSTAT_IO_R)
    822     0    stevel 	SET_SIZE(kstat_runq_enter)
    823     0    stevel 
    824     0    stevel 	.align 16
    825     0    stevel 	ENTRY(kstat_runq_exit)
    826     0    stevel 	GET_NATIVE_TIME(%g1, %g2, %g3)
    827     0    stevel 	KSTAT_Q_UPDATE(sub, BRZPN, kstat_q_panic, retl, KSTAT_IO_R)
    828     0    stevel 	SET_SIZE(kstat_runq_exit)
    829     0    stevel 
    830     0    stevel 	.align 16
    831     0    stevel 	ENTRY(kstat_waitq_to_runq)
    832     0    stevel 	GET_NATIVE_TIME(%g1, %g2, %g3)
    833     0    stevel 	KSTAT_Q_UPDATE(sub, BRZPN, kstat_q_panic, 1:, KSTAT_IO_W)
    834     0    stevel 	KSTAT_Q_UPDATE(add, BRZPT, 1f, 1:retl, KSTAT_IO_R)
    835     0    stevel 	SET_SIZE(kstat_waitq_to_runq)
    836     0    stevel 
    837     0    stevel 	.align 16
    838     0    stevel 	ENTRY(kstat_runq_back_to_waitq)
    839     0    stevel 	GET_NATIVE_TIME(%g1, %g2, %g3)
    840     0    stevel 	KSTAT_Q_UPDATE(sub, BRZPN, kstat_q_panic, 1:, KSTAT_IO_R)
    841     0    stevel 	KSTAT_Q_UPDATE(add, BRZPT, 1f, 1:retl, KSTAT_IO_W)
    842     0    stevel 	SET_SIZE(kstat_runq_back_to_waitq)
    843     0    stevel 
    844     0    stevel #endif	/* !(lint || __lint) */
    845     0    stevel 
    846     0    stevel #ifdef lint
    847     0    stevel 
    848     0    stevel int64_t timedelta;
    849     0    stevel hrtime_t hres_last_tick;
    850  4551   sudheer volatile timestruc_t hrestime;
    851     0    stevel int64_t hrestime_adj;
    852  4551   sudheer volatile int hres_lock;
    853     0    stevel uint_t nsec_scale;
    854     0    stevel hrtime_t hrtime_base;
    855     0    stevel int traptrace_use_stick;
    856     0    stevel 
    857     0    stevel #else	/* lint */
    858     0    stevel 	/*
    859     0    stevel 	 *  -- WARNING --
    860     0    stevel 	 *
    861     0    stevel 	 * The following variables MUST be together on a 128-byte boundary.
    862     0    stevel 	 * In addition to the primary performance motivation (having them all
    863     0    stevel 	 * on the same cache line(s)), code here and in the GET*TIME() macros
    864     0    stevel 	 * assumes that they all have the same high 22 address bits (so
    865     0    stevel 	 * there's only one sethi).
    866     0    stevel 	 */
    867     0    stevel 	.seg	".data"
    868     0    stevel 	.global	timedelta, hres_last_tick, hrestime, hrestime_adj
    869     0    stevel 	.global	hres_lock, nsec_scale, hrtime_base, traptrace_use_stick
    870     0    stevel 	.global	nsec_shift, adj_shift
    871     0    stevel 
    872     0    stevel 	/* XXX - above comment claims 128-bytes is necessary */
    873     0    stevel 	.align	64
    874     0    stevel timedelta:
    875     0    stevel 	.word	0, 0		/* int64_t */
    876     0    stevel hres_last_tick:
    877     0    stevel 	.word	0, 0		/* hrtime_t */
    878     0    stevel hrestime:
    879     0    stevel 	.nword	0, 0		/* 2 longs */
    880     0    stevel hrestime_adj:
    881     0    stevel 	.word	0, 0		/* int64_t */
    882     0    stevel hres_lock:
    883     0    stevel 	.word	0
    884     0    stevel nsec_scale:
    885     0    stevel 	.word	0
    886     0    stevel hrtime_base:
    887     0    stevel 	.word	0, 0
    888     0    stevel traptrace_use_stick:
    889     0    stevel 	.word	0
    890     0    stevel nsec_shift:
    891     0    stevel 	.word	NSEC_SHIFT
    892     0    stevel adj_shift:
    893     0    stevel 	.word	ADJ_SHIFT
    894     0    stevel 
    895     0    stevel #endif	/* lint */
    896     0    stevel 
    897     0    stevel 
    898     0    stevel /*
    899     0    stevel  * drv_usecwait(clock_t n)	[DDI/DKI - section 9F]
    900     0    stevel  * usec_delay(int n)		[compatibility - should go one day]
    901     0    stevel  * Delay by spinning.
    902     0    stevel  *
    903     0    stevel  * delay for n microseconds.  numbers <= 0 delay 1 usec
    904     0    stevel  *
    905     0    stevel  * With UltraSPARC-III the combination of supporting mixed-speed CPUs
    906     0    stevel  * and variable clock rate for power management requires that we
    907     0    stevel  * use %stick to implement this routine.
    908  1772  jl139090  *
    909  1772  jl139090  * For OPL platforms that support the "sleep" instruction, we
    910  1772  jl139090  * conditionally (ifdef'ed) insert a "sleep" instruction in
    911  1772  jl139090  * the loop. Note that theoritically we should have move (duplicated)
    912  1772  jl139090  * the code down to spitfire/us3/opl specific asm files - but this
    913  1772  jl139090  * is alot of code duplication just to add one "sleep" instruction.
    914  1772  jl139090  * We chose less code duplication for this.
    915     0    stevel  */
    916     0    stevel 
    917     0    stevel #if defined(lint)
    918     0    stevel 
    919     0    stevel /*ARGSUSED*/
    920     0    stevel void
    921     0    stevel drv_usecwait(clock_t n)
    922     0    stevel {}
    923     0    stevel 
    924     0    stevel /*ARGSUSED*/
    925     0    stevel void
    926     0    stevel usec_delay(int n)
    927     0    stevel {}
    928     0    stevel 
    929     0    stevel #else	/* lint */
    930     0    stevel 
    931     0    stevel 	ENTRY(drv_usecwait)
    932     0    stevel 	ALTENTRY(usec_delay)
    933     0    stevel 	brlez,a,pn %o0, 0f
    934     0    stevel 	mov	1, %o0
    935     0    stevel 0:
    936     0    stevel 	sethi	%hi(sticks_per_usec), %o1
    937     0    stevel 	lduw	[%o1 + %lo(sticks_per_usec)], %o1
    938     0    stevel 	mulx	%o1, %o0, %o1		! Scale usec to ticks
    939     0    stevel 	inc	%o1			! We don't start on a tick edge
    940     0    stevel 	GET_NATIVE_TIME(%o2, %o3, %o4)
    941     0    stevel 	add	%o1, %o2, %o1
    942     0    stevel 
    943  1772  jl139090 1:
    944  1772  jl139090 #ifdef	_OPL
    945  1772  jl139090 	.word 0x81b01060		! insert "sleep" instruction
    946  1772  jl139090 #endif /* _OPL */			! use byte code for now
    947  1772  jl139090 	cmp	%o1, %o2
    948     0    stevel 	GET_NATIVE_TIME(%o2, %o3, %o4)
    949     0    stevel 	bgeu,pt	%xcc, 1b
    950     0    stevel 	nop
    951     0    stevel 	retl
    952     0    stevel 	nop
    953     0    stevel 	SET_SIZE(usec_delay)
    954     0    stevel 	SET_SIZE(drv_usecwait)
    955     0    stevel #endif	/* lint */
    956     0    stevel 
    957     0    stevel #if defined(lint)
    958     0    stevel 
    959     0    stevel /* ARGSUSED */
    960     0    stevel void
    961     0    stevel pil14_interrupt(int level)
    962     0    stevel {}
    963     0    stevel 
    964     0    stevel #else	/* lint */
    965     0    stevel 
    966     0    stevel /*
    967     0    stevel  * Level-14 interrupt prologue.
    968     0    stevel  */
    969     0    stevel 	ENTRY_NP(pil14_interrupt)
    970     0    stevel 	CPU_ADDR(%g1, %g2)
    971     0    stevel 	rdpr	%pil, %g6			! %g6 = interrupted PIL
    972     0    stevel 	stn	%g6, [%g1 + CPU_PROFILE_PIL]	! record interrupted PIL
    973     0    stevel 	rdpr	%tstate, %g6
    974     0    stevel 	rdpr	%tpc, %g5
    975     0    stevel 	btst	TSTATE_PRIV, %g6		! trap from supervisor mode?
    976     0    stevel 	bnz,a,pt %xcc, 1f
    977     0    stevel 	stn	%g5, [%g1 + CPU_PROFILE_PC]	! if so, record kernel PC
    978     0    stevel 	stn	%g5, [%g1 + CPU_PROFILE_UPC]	! if not, record user PC
    979     0    stevel 	ba	pil_interrupt_common		! must be large-disp branch
    980     0    stevel 	stn	%g0, [%g1 + CPU_PROFILE_PC]	! zero kernel PC
    981     0    stevel 1:	ba	pil_interrupt_common		! must be large-disp branch
    982     0    stevel 	stn	%g0, [%g1 + CPU_PROFILE_UPC]	! zero user PC
    983     0    stevel 	SET_SIZE(pil14_interrupt)
    984     0    stevel 
    985     0    stevel 	ENTRY_NP(tick_rtt)
    986     0    stevel 	!
    987     0    stevel 	! Load TICK_COMPARE into %o5; if bit 63 is set, then TICK_COMPARE is
    988     0    stevel 	! disabled.  If TICK_COMPARE is enabled, we know that we need to
    989     0    stevel 	! reenqueue the interrupt request structure.  We'll then check TICKINT
    990     0    stevel 	! in SOFTINT; if it's set, then we know that we were in a TICK_COMPARE
    991     0    stevel 	! interrupt.  In this case, TICK_COMPARE may have been rewritten
    992     0    stevel 	! recently; we'll compare %o5 to the current time to verify that it's
    993     0    stevel 	! in the future.
    994     0    stevel 	!
    995     0    stevel 	! Note that %o5 is live until after 1f.
    996     0    stevel 	! XXX - there is a subroutine call while %o5 is live!
    997     0    stevel 	!
    998     0    stevel 	RD_TICKCMPR(%o5, %g1)
    999     0    stevel 	srlx	%o5, TICKINT_DIS_SHFT, %g1
   1000     0    stevel 	brnz,pt	%g1, 2f
   1001     0    stevel 	nop
   1002     0    stevel 
   1003     0    stevel 	rdpr 	%pstate, %g5
   1004     0    stevel 	andn	%g5, PSTATE_IE, %g1
   1005     0    stevel 	wrpr	%g0, %g1, %pstate		! Disable vec interrupts
   1006     0    stevel 
   1007     0    stevel 	sethi	%hi(cbe_level14_inum), %o1
   1008  2973   govinda 	ldx	[%o1 + %lo(cbe_level14_inum)], %o1
   1009     0    stevel 	call	intr_enqueue_req ! preserves %o5 and %g5
   1010     0    stevel 	mov	PIL_14, %o0
   1011     0    stevel 
   1012     0    stevel 	! Check SOFTINT for TICKINT/STICKINT
   1013     0    stevel 	rd	SOFTINT, %o4
   1014     0    stevel 	set	(TICK_INT_MASK | STICK_INT_MASK), %o0
   1015     0    stevel 	andcc	%o4, %o0, %g0
   1016     0    stevel 	bz,a,pn	%icc, 2f
   1017     0    stevel 	wrpr	%g0, %g5, %pstate		! Enable vec interrupts
   1018     0    stevel 
   1019     0    stevel 	! clear TICKINT/STICKINT
   1020     0    stevel 	wr	%o0, CLEAR_SOFTINT
   1021     0    stevel 
   1022     0    stevel 	!
   1023     0    stevel 	! Now that we've cleared TICKINT, we can reread %tick and confirm
   1024     0    stevel 	! that the value we programmed is still in the future.  If it isn't,
   1025     0    stevel 	! we need to reprogram TICK_COMPARE to fire as soon as possible.
   1026     0    stevel 	!
   1027     0    stevel 	GET_NATIVE_TIME(%o0, %g1, %g2)		! %o0 = tick
   1028     0    stevel 	sllx	%o0, 1, %o0			! Clear the DIS bit
   1029     0    stevel 	srlx	%o0, 1, %o0
   1030     0    stevel 	cmp	%o5, %o0			! In the future?
   1031     0    stevel 	bg,a,pt	%xcc, 2f			! Yes, drive on.
   1032     0    stevel 	wrpr	%g0, %g5, %pstate		!   delay: enable vec intr
   1033     0    stevel 
   1034     0    stevel 	!
   1035     0    stevel 	! If we're here, then we have programmed TICK_COMPARE with a %tick
   1036     0    stevel 	! which is in the past; we'll now load an initial step size, and loop
   1037     0    stevel 	! until we've managed to program TICK_COMPARE to fire in the future.
   1038     0    stevel 	!
   1039     0    stevel 	mov	8, %o4				! 8 = arbitrary inital step
   1040     0    stevel 1:	add	%o0, %o4, %o5			! Add the step
   1041     0    stevel 	WR_TICKCMPR(%o5,%g1,%g2,__LINE__)	! Write to TICK_CMPR
   1042     0    stevel 	GET_NATIVE_TIME(%o0, %g1, %g2)		! %o0 = tick
   1043     0    stevel 	sllx	%o0, 1, %o0			! Clear the DIS bit
   1044     0    stevel 	srlx	%o0, 1, %o0
   1045     0    stevel 	cmp	%o5, %o0			! In the future?
   1046     0    stevel 	bg,a,pt	%xcc, 2f			! Yes, drive on.
   1047     0    stevel 	wrpr	%g0, %g5, %pstate		!    delay: enable vec intr
   1048     0    stevel 	ba	1b				! No, try again.
   1049     0    stevel 	sllx	%o4, 1, %o4			!    delay: double step size
   1050     0    stevel 
   1051     0    stevel 2:	ba	current_thread_complete
   1052     0    stevel 	nop
   1053     0    stevel 	SET_SIZE(tick_rtt)
   1054     0    stevel 
   1055     0    stevel #endif	/* lint */
   1056  8803  Jonathan 
   1057  8803  Jonathan #if defined(lint)
   1058  8803  Jonathan 
   1059  8803  Jonathan /* ARGSUSED */
   1060  8803  Jonathan void
   1061  8803  Jonathan pil15_interrupt(int level)
   1062  8803  Jonathan {}
   1063  8803  Jonathan 
   1064  8803  Jonathan #else  /* lint */
   1065  8803  Jonathan 
   1066  8803  Jonathan /*
   1067  8803  Jonathan  * Level-15 interrupt prologue.
   1068  8803  Jonathan  */
   1069  8803  Jonathan        ENTRY_NP(pil15_interrupt)
   1070  8803  Jonathan        CPU_ADDR(%g1, %g2)
   1071  8803  Jonathan        rdpr    %tstate, %g6
   1072  8803  Jonathan        rdpr    %tpc, %g5
   1073  8803  Jonathan        btst    TSTATE_PRIV, %g6                ! trap from supervisor mode?
   1074  8803  Jonathan        bnz,a,pt %xcc, 1f
   1075  8803  Jonathan        stn     %g5, [%g1 + CPU_CPCPROFILE_PC]  ! if so, record kernel PC
   1076  8803  Jonathan        stn     %g5, [%g1 + CPU_CPCPROFILE_UPC] ! if not, record user PC
   1077  8803  Jonathan        ba      pil15_epilogue                  ! must be large-disp branch
   1078  8803  Jonathan        stn     %g0, [%g1 + CPU_CPCPROFILE_PC]  ! zero kernel PC
   1079  8803  Jonathan 1:     ba      pil15_epilogue                  ! must be large-disp branch
   1080  8803  Jonathan        stn     %g0, [%g1 + CPU_CPCPROFILE_UPC] ! zero user PC
   1081  8803  Jonathan        SET_SIZE(pil15_interrupt)
   1082  8803  Jonathan 
   1083  8803  Jonathan #endif /* lint */
   1084     0    stevel 
   1085     0    stevel #if defined(lint) || defined(__lint)
   1086     0    stevel 
   1087     0    stevel /* ARGSUSED */
   1088     0    stevel uint64_t
   1089     0    stevel find_cpufrequency(volatile uchar_t *clock_ptr)
   1090     0    stevel {
   1091     0    stevel 	return (0);
   1092     0    stevel }
   1093     0    stevel 
   1094     0    stevel #else	/* lint */
   1095     0    stevel 
   1096     0    stevel #ifdef DEBUG
   1097     0    stevel 	.seg	".text"
   1098     0    stevel find_cpufreq_panic:
   1099     0    stevel 	.asciz	"find_cpufrequency: interrupts already disabled on entry"
   1100     0    stevel #endif	/* DEBUG */
   1101     0    stevel 
   1102     0    stevel 	ENTRY_NP(find_cpufrequency)
   1103     0    stevel 	rdpr	%pstate, %g1
   1104     0    stevel 
   1105     0    stevel #ifdef DEBUG
   1106     0    stevel 	andcc	%g1, PSTATE_IE, %g0	! If DEBUG, check that interrupts
   1107     0    stevel 	bnz	0f			! are currently enabled
   1108     0    stevel 	sethi	%hi(find_cpufreq_panic), %o1
   1109     0    stevel 	call	panic
   1110     0    stevel 	or	%o1, %lo(find_cpufreq_panic), %o0
   1111     0    stevel #endif	/* DEBUG */
   1112     0    stevel 
   1113     0    stevel 0:
   1114     0    stevel 	wrpr	%g1, PSTATE_IE, %pstate	! Disable interrupts
   1115     0    stevel 3:
   1116     0    stevel 	ldub	[%o0], %o1		! Read the number of seconds
   1117     0    stevel 	mov	%o1, %o2		! remember initial value in %o2
   1118     0    stevel 1:
   1119     0    stevel 	GET_NATIVE_TIME(%o3, %g4, %g5)
   1120     0    stevel 	cmp	%o1, %o2		! did the seconds register roll over?
   1121     0    stevel 	be,pt	%icc, 1b		! branch back if unchanged
   1122     0    stevel 	ldub	[%o0], %o2		!   delay: load the new seconds val
   1123     0    stevel 
   1124     0    stevel 	brz,pn	%o2, 3b			! if the minutes just rolled over,
   1125     0    stevel 					! the last second could have been
   1126     0    stevel 					! inaccurate; try again.
   1127     0    stevel 	mov	%o2, %o4		!   delay: store init. val. in %o2
   1128     0    stevel 2:
   1129     0    stevel 	GET_NATIVE_TIME(%o5, %g4, %g5)
   1130     0    stevel 	cmp	%o2, %o4		! did the seconds register roll over?
   1131     0    stevel 	be,pt	%icc, 2b		! branch back if unchanged
   1132     0    stevel 	ldub	[%o0], %o4		!   delay: load the new seconds val
   1133     0    stevel 
   1134     0    stevel 	brz,pn	%o4, 0b			! if the minutes just rolled over,
   1135     0    stevel 					! the last second could have been
   1136     0    stevel 					! inaccurate; try again.
   1137     0    stevel 	wrpr	%g0, %g1, %pstate	!   delay: re-enable interrupts
   1138     0    stevel 
   1139     0    stevel 	retl
   1140     0    stevel 	sub	%o5, %o3, %o0		! return the difference in ticks
   1141     0    stevel 	SET_SIZE(find_cpufrequency)
   1142     0    stevel 
   1143     0    stevel #endif	/* lint */
   1144     0    stevel 
   1145     0    stevel #if defined(lint)
   1146     0    stevel /*
   1147     0    stevel  * Prefetch a page_t for write or read, this assumes a linear
   1148     0    stevel  * scan of sequential page_t's.
   1149     0    stevel  */
   1150     0    stevel /*ARGSUSED*/
   1151     0    stevel void
   1152     0    stevel prefetch_page_w(void *pp)
   1153     0    stevel {}
   1154     0    stevel 
   1155     0    stevel /*ARGSUSED*/
   1156     0    stevel void
   1157     0    stevel prefetch_page_r(void *pp)
   1158     0    stevel {}
   1159     0    stevel #else	/* lint */
   1160     0    stevel 
   1161     0    stevel #if defined(CHEETAH) || defined(CHEETAH_PLUS) || defined(JALAPENO) || \
   1162     0    stevel 	defined(SERRANO)
   1163     0    stevel 	!
   1164     0    stevel 	! On US-III, the prefetch instruction queue is 8 entries deep.
   1165     0    stevel 	! Also, prefetches for write put data in the E$, which has
   1166     0    stevel 	! lines of 512 bytes for an 8MB cache. Each E$ line is further
   1167     0    stevel 	! subblocked into 64 byte chunks.
   1168     0    stevel 	!
   1169     0    stevel 	! Since prefetch can only bring in 64 bytes at a time (See Sparc
   1170     0    stevel 	! v9 Architecture Manual pp.204) and a page_t is 128 bytes,
   1171     0    stevel 	! then 2 prefetches are required in order to bring an entire
   1172     0    stevel 	! page into the E$.
   1173     0    stevel 	!
   1174     0    stevel 	! Since the prefetch queue is 8 entries deep, we currently can
   1175     0    stevel 	! only have 4 prefetches for page_t's outstanding. Thus, we
   1176     0    stevel 	! prefetch n+4 ahead of where we are now:
   1177     0    stevel 	!
   1178     0    stevel 	!      4 * sizeof(page_t)     -> 512
   1179     0    stevel 	!      4 * sizeof(page_t) +64 -> 576
   1180     0    stevel 	!
   1181     0    stevel 	! Example
   1182     0    stevel 	! =======
   1183     0    stevel 	! contiguous page array in memory...
   1184     0    stevel 	!
   1185     0    stevel 	! |AAA1|AAA2|BBB1|BBB2|CCC1|CCC2|DDD1|DDD2|XXX1|XXX2|YYY1|YYY2|...
   1186     0    stevel 	! ^         ^         ^         ^         ^    ^
   1187     0    stevel 	! pp                                      |    pp+4*sizeof(page)+64
   1188     0    stevel 	!                                         |
   1189     0    stevel 	!                                         pp+4*sizeof(page)
   1190     0    stevel 	!
   1191     0    stevel 	!  Prefetch
   1192     0    stevel 	!   Queue
   1193     0    stevel 	! +-------+<--- In this iteration, we're working with pp (AAA1),
   1194     0    stevel 	! |Preftch|     but we enqueue prefetch for addr = XXX1
   1195     0    stevel 	! | XXX1  |
   1196     0    stevel 	! +-------+<--- this queue slot will be a prefetch instruction for
   1197     0    stevel 	! |Preftch|     for addr = pp + 4*sizeof(page_t) + 64 (or second
   1198     0    stevel 	! | XXX2  |     half of page XXX)
   1199     0    stevel 	! +-------+
   1200     0    stevel 	! |Preftch|<-+- The next time around this function, we'll be
   1201     0    stevel 	! | YYY1  |  |  working with pp = BBB1, but will be enqueueing
   1202     0    stevel 	! +-------+  |  prefetches to for both halves of page YYY,
   1203     0    stevel 	! |Preftch|  |  while both halves of page XXX are in transit
   1204     0    stevel 	! | YYY2  |<-+  make their way into the E$.
   1205     0    stevel 	! +-------+
   1206     0    stevel 	! |Preftch|
   1207     0    stevel 	! | ZZZ1  |
   1208     0    stevel 	! +-------+
   1209     0    stevel 	! .       .
   1210     0    stevel 	! :       :
   1211     0    stevel 	!
   1212     0    stevel 	!  E$
   1213     0    stevel 	! +============================================...
   1214     0    stevel 	! | XXX1 | XXX2 | YYY1 | YYY2 | ZZZ1 | ZZZ2 |
   1215     0    stevel 	! +============================================...
   1216     0    stevel 	! |      |      |      |      |      |      |
   1217     0    stevel 	! +============================================...
   1218     0    stevel 	! .
   1219     0    stevel 	! :
   1220     0    stevel 	!
   1221     0    stevel 	! So we should expect the first four page accesses to stall
   1222     0    stevel 	! while we warm up the cache, afterwhich, most of the pages
   1223     0    stevel 	! will have their pp ready in the E$.
   1224     0    stevel 	!
   1225     0    stevel 	! Also note that if sizeof(page_t) grows beyond 128, then
   1226     0    stevel 	! we'll need an additional prefetch to get an entire page
   1227     0    stevel 	! into the E$, thus reducing the number of outstanding page
   1228     0    stevel 	! prefetches to 2 (ie. 3 prefetches/page = 6 queue slots)
   1229     0    stevel 	! etc.
   1230     0    stevel 	!
   1231     0    stevel 	! Cheetah+
   1232     0    stevel 	! ========
   1233     0    stevel 	! On Cheetah+ we use "#n_write" prefetches as these avoid
   1234     0    stevel 	! unnecessary RTS->RTO bus transaction state change, and
   1235     0    stevel 	! just issues RTO transaction. (See pp.77 of Cheetah+ Delta
   1236     0    stevel 	! PRM). On Cheetah, #n_write prefetches are reflected with
   1237     0    stevel 	! RTS->RTO state transition regardless.
   1238     0    stevel 	!
   1239     0    stevel #define STRIDE1 512
   1240     0    stevel #define STRIDE2 576
   1241     0    stevel 
   1242     0    stevel #if	STRIDE1 != (PAGE_SIZE * 4)
   1243     0    stevel #error	"STRIDE1 != (PAGE_SIZE * 4)"
   1244     0    stevel #endif	/* STRIDE1 != (PAGE_SIZE * 4) */
   1245     0    stevel 
   1246     0    stevel         ENTRY(prefetch_page_w)
   1247     0    stevel         prefetch        [%o0+STRIDE1], #n_writes
   1248     0    stevel         retl
   1249     0    stevel         prefetch        [%o0+STRIDE2], #n_writes
   1250     0    stevel         SET_SIZE(prefetch_page_w)
   1251     0    stevel 
   1252     0    stevel 	!
   1253     0    stevel 	! Note on CHEETAH to prefetch for read, we really use #one_write.
   1254     0    stevel 	! This fetches to E$ (general use) rather than P$ (floating point use).
   1255     0    stevel 	!
   1256     0    stevel         ENTRY(prefetch_page_r)
   1257     0    stevel         prefetch        [%o0+STRIDE1], #one_write
   1258     0    stevel         retl
   1259     0    stevel         prefetch        [%o0+STRIDE2], #one_write
   1260     0    stevel         SET_SIZE(prefetch_page_r)
   1261     0    stevel 
   1262     0    stevel #elif defined(SPITFIRE) || defined(HUMMINGBIRD)
   1263     0    stevel 
   1264     0    stevel 	!
   1265     0    stevel 	! UltraSparcII can have up to 3 prefetches outstanding.
   1266     0    stevel 	! A page_t is 128 bytes (2 prefetches of 64 bytes each)
   1267     0    stevel 	! So prefetch for pp + 1, which is
   1268     0    stevel 	!
   1269     0    stevel 	!       pp + sizeof(page_t)
   1270     0    stevel 	! and
   1271     0    stevel 	!       pp + sizeof(page_t) + 64
   1272     0    stevel 	!
   1273     0    stevel #define STRIDE1	128
   1274     0    stevel #define STRIDE2	192
   1275     0    stevel 
   1276     0    stevel #if	STRIDE1 != PAGE_SIZE
   1277     0    stevel #error	"STRIDE1 != PAGE_SIZE"
   1278     0    stevel #endif	/* STRIDE1 != PAGE_SIZE */
   1279     0    stevel 
   1280     0    stevel         ENTRY(prefetch_page_w)
   1281     0    stevel         prefetch        [%o0+STRIDE1], #n_writes
   1282     0    stevel         retl
   1283     0    stevel         prefetch        [%o0+STRIDE2], #n_writes
   1284     0    stevel         SET_SIZE(prefetch_page_w)
   1285     0    stevel 
   1286     0    stevel         ENTRY(prefetch_page_r)
   1287     0    stevel         prefetch        [%o0+STRIDE1], #n_reads
   1288     0    stevel         retl
   1289     0    stevel         prefetch        [%o0+STRIDE2], #n_reads
   1290     0    stevel         SET_SIZE(prefetch_page_r)
   1291  1772  jl139090 
   1292  1772  jl139090 #elif defined(OLYMPUS_C)
   1293  1772  jl139090 	!
   1294  1856       hyw 	! Prefetch strides for Olympus-C
   1295  1772  jl139090 	!
   1296  1772  jl139090 
   1297  1856       hyw #define STRIDE1	0x440
   1298  1856       hyw #define STRIDE2	0x640
   1299  1772  jl139090 
   1300  1772  jl139090 	ENTRY(prefetch_page_w)
   1301  1772  jl139090         prefetch        [%o0+STRIDE1], #n_writes
   1302  1772  jl139090 	retl
   1303  1772  jl139090         prefetch        [%o0+STRIDE2], #n_writes
   1304  1772  jl139090 	SET_SIZE(prefetch_page_w)
   1305  1772  jl139090 
   1306  1772  jl139090 	ENTRY(prefetch_page_r)
   1307  1772  jl139090         prefetch        [%o0+STRIDE1], #n_writes
   1308  1772  jl139090 	retl
   1309  1772  jl139090         prefetch        [%o0+STRIDE2], #n_writes
   1310  1772  jl139090 	SET_SIZE(prefetch_page_r)
   1311  1772  jl139090 #else	/* OLYMPUS_C */
   1312     0    stevel 
   1313     0    stevel #error "You need to fix this for your new cpu type."
   1314     0    stevel 
   1315  1772  jl139090 #endif	/* OLYMPUS_C */
   1316     0    stevel 
   1317     0    stevel #endif	/* lint */
   1318     0    stevel 
   1319     0    stevel #if defined(lint)
   1320     0    stevel /*
   1321     0    stevel  * Prefetch struct smap for write.
   1322     0    stevel  */
   1323     0    stevel /*ARGSUSED*/
   1324     0    stevel void
   1325     0    stevel prefetch_smap_w(void *smp)
   1326     0    stevel {}
   1327     0    stevel #else	/* lint */
   1328     0    stevel 
   1329     0    stevel #if defined(CHEETAH) || defined(CHEETAH_PLUS) || defined(JALAPENO) || \
   1330     0    stevel 	defined(SERRANO)
   1331     0    stevel 
   1332     0    stevel #define	PREFETCH_Q_LEN 8
   1333     0    stevel 
   1334     0    stevel #elif defined(SPITFIRE) || defined(HUMMINGBIRD)
   1335     0    stevel 
   1336     0    stevel #define	PREFETCH_Q_LEN 3
   1337     0    stevel 
   1338  1772  jl139090 #elif defined(OLYMPUS_C)
   1339  1772  jl139090 	!
   1340  1856       hyw 	! Use length of one for now.
   1341  1856       hyw 	!
   1342  1772  jl139090 #define	PREFETCH_Q_LEN	1
   1343  1772  jl139090 
   1344  1772  jl139090 #else 	/* OLYMPUS_C */
   1345     0    stevel 
   1346     0    stevel #error You need to fix this for your new cpu type.
   1347     0    stevel 
   1348  1772  jl139090 #endif	/* OLYMPUS_C */
   1349     0    stevel 
   1350     0    stevel #include <vm/kpm.h>
   1351     0    stevel 
   1352     0    stevel #ifdef	SEGKPM_SUPPORT
   1353     0    stevel 
   1354     0    stevel #define	SMAP_SIZE 72
   1355     0    stevel #define SMAP_STRIDE (((PREFETCH_Q_LEN * 64) / SMAP_SIZE) * 64)
   1356     0    stevel 
   1357     0    stevel #else	/* SEGKPM_SUPPORT */
   1358     0    stevel 
   1359     0    stevel 	!
   1360     0    stevel 	! The hardware will prefetch the 64 byte cache aligned block
   1361     0    stevel 	! that contains the address specified in the prefetch instruction.
   1362     0    stevel 	! Since the size of the smap struct is 48 bytes, issuing 1 prefetch
   1363     0    stevel 	! per pass will suffice as long as we prefetch far enough ahead to
   1364     0    stevel 	! make sure we don't stall for the cases where the smap object
   1365     0    stevel 	! spans multiple hardware prefetch blocks.  Let's prefetch as far
   1366     0    stevel 	! ahead as the hardware will allow.
   1367     0    stevel 	!
   1368     0    stevel 	! The smap array is processed with decreasing address pointers.
   1369     0    stevel 	!
   1370     0    stevel #define	SMAP_SIZE 48
   1371     0    stevel #define	SMAP_STRIDE (PREFETCH_Q_LEN * SMAP_SIZE)
   1372     0    stevel 
   1373     0    stevel #endif	/* SEGKPM_SUPPORT */
   1374     0    stevel 
   1375     0    stevel 	ENTRY(prefetch_smap_w)
   1376     0    stevel 	retl
   1377     0    stevel 	prefetch	[%o0-SMAP_STRIDE], #n_writes
   1378     0    stevel 	SET_SIZE(prefetch_smap_w)
   1379     0    stevel 
   1380     0    stevel #endif	/* lint */
   1381     0    stevel 
   1382     0    stevel #if defined(lint) || defined(__lint)
   1383     0    stevel 
   1384     0    stevel /* ARGSUSED */
   1385     0    stevel uint64_t
   1386     0    stevel getidsr(void)
   1387     0    stevel { return 0; }
   1388     0    stevel 
   1389     0    stevel #else	/* lint */
   1390     0    stevel 
   1391     0    stevel 	ENTRY_NP(getidsr)
   1392     0    stevel 	retl
   1393     0    stevel 	ldxa	[%g0]ASI_INTR_DISPATCH_STATUS, %o0
   1394     0    stevel 	SET_SIZE(getidsr)
   1395     0    stevel 
   1396     0    stevel #endif	/* lint */
   1397