xref: /illumos-gate/usr/src/uts/sun4u/cpu/common_asm.S (revision 5d9d9091)
17c478bd9Sstevel@tonic-gate/*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
525cf1a30Sjl * Common Development and Distribution License (the "License").
625cf1a30Sjl * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate/*
22b52a336eSPavel Tatashin * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate */
247c478bd9Sstevel@tonic-gate
257c478bd9Sstevel@tonic-gate#include "assym.h"
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate/*
287c478bd9Sstevel@tonic-gate * General assembly language routines.
297c478bd9Sstevel@tonic-gate * It is the intent of this file to contain routines that are
307c478bd9Sstevel@tonic-gate * specific to cpu architecture.
317c478bd9Sstevel@tonic-gate */
327c478bd9Sstevel@tonic-gate
337c478bd9Sstevel@tonic-gate/*
347c478bd9Sstevel@tonic-gate * WARNING: If you add a fast trap handler which can be invoked by a
357c478bd9Sstevel@tonic-gate * non-privileged user, you may have to use the FAST_TRAP_DONE macro
367c478bd9Sstevel@tonic-gate * instead of "done" instruction to return back to the user mode. See
377c478bd9Sstevel@tonic-gate * comments for the "fast_trap_done" entry point for more information.
387c478bd9Sstevel@tonic-gate */
397c478bd9Sstevel@tonic-gate#define	FAST_TRAP_DONE	\
407c478bd9Sstevel@tonic-gate	ba,a	fast_trap_done
417c478bd9Sstevel@tonic-gate
427c478bd9Sstevel@tonic-gate/*
437c478bd9Sstevel@tonic-gate * Override GET_NATIVE_TIME for the cpu module code.  This is not
447c478bd9Sstevel@tonic-gate * guaranteed to be exactly one instruction, be careful of using
457c478bd9Sstevel@tonic-gate * the macro in delay slots.
467c478bd9Sstevel@tonic-gate *
47*5d9d9091SRichard Lowe * Do not use any instruction that modifies condition codes as the
487c478bd9Sstevel@tonic-gate * caller may depend on these to remain unchanged across the macro.
497c478bd9Sstevel@tonic-gate */
5025cf1a30Sjl#if defined(CHEETAH) || defined(OLYMPUS_C)
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate#define	GET_NATIVE_TIME(out, scr1, scr2) \
537c478bd9Sstevel@tonic-gate	rd	STICK, out
547c478bd9Sstevel@tonic-gate#define	DELTA_NATIVE_TIME(delta, reg, scr1, scr2, scr3) \
557c478bd9Sstevel@tonic-gate	rd	STICK, reg;		\
567c478bd9Sstevel@tonic-gate	add	reg, delta, reg;	\
577c478bd9Sstevel@tonic-gate	wr	reg, STICK
587c478bd9Sstevel@tonic-gate#define	RD_TICKCMPR(out, scr)		\
597c478bd9Sstevel@tonic-gate	rd	STICK_COMPARE, out
607c478bd9Sstevel@tonic-gate#define	WR_TICKCMPR(in, scr1, scr2, label) \
617c478bd9Sstevel@tonic-gate	wr	in, STICK_COMPARE
627c478bd9Sstevel@tonic-gate
637c478bd9Sstevel@tonic-gate#elif defined(HUMMINGBIRD)
647c478bd9Sstevel@tonic-gate#include <sys/spitregs.h>
657c478bd9Sstevel@tonic-gate
667c478bd9Sstevel@tonic-gate/*
677c478bd9Sstevel@tonic-gate * the current hummingbird version of %stick and %stick_cmp
687c478bd9Sstevel@tonic-gate * were both implemented as (2) 32-bit locations in ASI_IO space;
697c478bd9Sstevel@tonic-gate * the hdwr should support atomic r/w; meanwhile: ugly alert! ...
707c478bd9Sstevel@tonic-gate *
717c478bd9Sstevel@tonic-gate * 64-bit opcodes are required, but move only 32-bits:
727c478bd9Sstevel@tonic-gate *
737c478bd9Sstevel@tonic-gate * ldxa [phys]ASI_IO, %dst 	reads  the low 32-bits from phys into %dst
747c478bd9Sstevel@tonic-gate * stxa %src, [phys]ASI_IO 	writes the low 32-bits from %src into phys
757c478bd9Sstevel@tonic-gate *
767c478bd9Sstevel@tonic-gate * reg equivalent		[phys]ASI_IO
777c478bd9Sstevel@tonic-gate * ------------------		---------------
787c478bd9Sstevel@tonic-gate * %stick_cmp  low-32		0x1FE.0000.F060
797c478bd9Sstevel@tonic-gate * %stick_cmp high-32		0x1FE.0000.F068
807c478bd9Sstevel@tonic-gate * %stick      low-32		0x1FE.0000.F070
817c478bd9Sstevel@tonic-gate * %stick     high-32		0x1FE.0000.F078
827c478bd9Sstevel@tonic-gate */
837c478bd9Sstevel@tonic-gate#define	HSTC_LOW	0x60			/* stick_cmp low  32-bits */
847c478bd9Sstevel@tonic-gate#define	HSTC_HIGH	0x68			/* stick_cmp high 32-bits */
857c478bd9Sstevel@tonic-gate#define	HST_LOW		0x70			/* stick low  32-bits */
867c478bd9Sstevel@tonic-gate#define	HST_HIGH	0x78			/* stick high 32-bits */
877c478bd9Sstevel@tonic-gate#define	HST_DIFF	0x08			/* low<-->high diff */
887c478bd9Sstevel@tonic-gate
897c478bd9Sstevel@tonic-gate/*
907c478bd9Sstevel@tonic-gate * Any change in the number of instructions in SETL41()
917c478bd9Sstevel@tonic-gate * will affect SETL41_OFF
927c478bd9Sstevel@tonic-gate */
937c478bd9Sstevel@tonic-gate#define	SETL41(reg, byte) \
947c478bd9Sstevel@tonic-gate	sethi	%hi(0x1FE00000), reg;		/* 0000.0000.1FE0.0000 */ \
957c478bd9Sstevel@tonic-gate	or	reg, 0xF, reg;			/* 0000.0000.1FE0.000F */ \
967c478bd9Sstevel@tonic-gate	sllx	reg, 12, reg;			/* 0000.01FE.0000.F000 */ \
977c478bd9Sstevel@tonic-gate	or	reg, byte, reg;			/* 0000.01FE.0000.F0xx */
987c478bd9Sstevel@tonic-gate
997c478bd9Sstevel@tonic-gate/*
1007c478bd9Sstevel@tonic-gate * SETL41_OFF is used to calulate the relative PC value when a
1017c478bd9Sstevel@tonic-gate * branch instruction needs to go over SETL41() macro
1027c478bd9Sstevel@tonic-gate */
1037c478bd9Sstevel@tonic-gate#define SETL41_OFF  16
1047c478bd9Sstevel@tonic-gate
1057c478bd9Sstevel@tonic-gate/*
1067c478bd9Sstevel@tonic-gate * reading stick requires 2 loads, and there could be an intervening
1077c478bd9Sstevel@tonic-gate * low-to-high 32-bit rollover resulting in a return value that is
1087c478bd9Sstevel@tonic-gate * off by about (2 ^ 32); this rare case is prevented by re-reading
1097c478bd9Sstevel@tonic-gate * the low-32 bits after the high-32 and verifying the "after" value
1107c478bd9Sstevel@tonic-gate * is >= the "before" value; if not, increment the high-32 value.
1117c478bd9Sstevel@tonic-gate *
1127c478bd9Sstevel@tonic-gate * this method is limited to 1 rollover, and based on the fixed
1137c478bd9Sstevel@tonic-gate * stick-frequency (5555555), requires the loads to complete within
1147c478bd9Sstevel@tonic-gate * 773 seconds; incrementing the high-32 value will not overflow for
1157c478bd9Sstevel@tonic-gate * about 52644 years.
1167c478bd9Sstevel@tonic-gate *
1177c478bd9Sstevel@tonic-gate * writing stick requires 2 stores; if the old/new low-32 value is
1187c478bd9Sstevel@tonic-gate * near 0xffffffff, there could be another rollover (also rare).
1197c478bd9Sstevel@tonic-gate * to prevent this, we first write a 0 to the low-32, then write
1207c478bd9Sstevel@tonic-gate * new values to the high-32 then the low-32.
1217c478bd9Sstevel@tonic-gate *
1227c478bd9Sstevel@tonic-gate * When we detect a carry in the lower %stick register, we need to
1237c478bd9Sstevel@tonic-gate * read HST_HIGH again. However at the point where we detect this,
1247c478bd9Sstevel@tonic-gate * we need to rebuild the register address HST_HIGH.This involves more
1257c478bd9Sstevel@tonic-gate * than one instructions and a branch is unavoidable. However, most of
1267c478bd9Sstevel@tonic-gate * the time, there is no carry. So we take the penalty of a branch
1277c478bd9Sstevel@tonic-gate * instruction only when there is carry (less frequent).
128*5d9d9091SRichard Lowe *
1297c478bd9Sstevel@tonic-gate * For GET_NATIVE_TIME(), we start afresh and branch to SETL41().
1307c478bd9Sstevel@tonic-gate * For DELTA_NATIVE_TIME(), we branch to just after SETL41() since
1317c478bd9Sstevel@tonic-gate * addr already points to HST_LOW.
1327c478bd9Sstevel@tonic-gate *
1337c478bd9Sstevel@tonic-gate * NOTE: this method requires disabling interrupts before using
1347c478bd9Sstevel@tonic-gate * DELTA_NATIVE_TIME.
1357c478bd9Sstevel@tonic-gate */
1367c478bd9Sstevel@tonic-gate#define	GET_NATIVE_TIME(out, scr, tmp)	\
1377c478bd9Sstevel@tonic-gate	SETL41(scr, HST_LOW);		\
1387c478bd9Sstevel@tonic-gate	ldxa	[scr]ASI_IO, tmp;	\
1397c478bd9Sstevel@tonic-gate	inc	HST_DIFF, scr;		\
1407c478bd9Sstevel@tonic-gate	ldxa	[scr]ASI_IO, out;	\
1417c478bd9Sstevel@tonic-gate	dec	HST_DIFF, scr;		\
1427c478bd9Sstevel@tonic-gate	ldxa	[scr]ASI_IO, scr;	\
1437c478bd9Sstevel@tonic-gate	sub	scr, tmp, tmp;		\
1447c478bd9Sstevel@tonic-gate	brlz,pn tmp, .-(SETL41_OFF+24); \
1457c478bd9Sstevel@tonic-gate	sllx	out, 32, out;		\
1467c478bd9Sstevel@tonic-gate	or	out, scr, out
1477c478bd9Sstevel@tonic-gate#define	DELTA_NATIVE_TIME(delta, addr, high, low, tmp) \
1487c478bd9Sstevel@tonic-gate	SETL41(addr, HST_LOW);		\
1497c478bd9Sstevel@tonic-gate	ldxa	[addr]ASI_IO, tmp;	\
1507c478bd9Sstevel@tonic-gate	inc	HST_DIFF, addr;		\
1517c478bd9Sstevel@tonic-gate	ldxa	[addr]ASI_IO, high;	\
1527c478bd9Sstevel@tonic-gate	dec	HST_DIFF, addr;		\
1537c478bd9Sstevel@tonic-gate	ldxa	[addr]ASI_IO, low;	\
1547c478bd9Sstevel@tonic-gate	sub	low, tmp, tmp;		\
1557c478bd9Sstevel@tonic-gate	brlz,pn tmp, .-24;		\
1567c478bd9Sstevel@tonic-gate	sllx	high, 32, high;		\
1577c478bd9Sstevel@tonic-gate	or	high, low, high;	\
1587c478bd9Sstevel@tonic-gate	add	high, delta, high;	\
1597c478bd9Sstevel@tonic-gate	srl	high, 0, low;		\
1607c478bd9Sstevel@tonic-gate	srlx	high, 32, high;		\
1617c478bd9Sstevel@tonic-gate	stxa	%g0, [addr]ASI_IO;	\
1627c478bd9Sstevel@tonic-gate	inc	HST_DIFF, addr;		\
1637c478bd9Sstevel@tonic-gate	stxa	high, [addr]ASI_IO;	\
1647c478bd9Sstevel@tonic-gate	dec	HST_DIFF, addr;		\
1657c478bd9Sstevel@tonic-gate	stxa	low, [addr]ASI_IO
1667c478bd9Sstevel@tonic-gate#define RD_TICKCMPR(out, scr)		\
1677c478bd9Sstevel@tonic-gate	SETL41(scr, HSTC_LOW);		\
1687c478bd9Sstevel@tonic-gate	ldxa	[scr]ASI_IO, out;	\
1697c478bd9Sstevel@tonic-gate	inc	HST_DIFF, scr;		\
1707c478bd9Sstevel@tonic-gate	ldxa	[scr]ASI_IO, scr;	\
1717c478bd9Sstevel@tonic-gate	sllx	scr, 32, scr;		\
1727c478bd9Sstevel@tonic-gate	or	scr, out, out
1737c478bd9Sstevel@tonic-gate#define WR_TICKCMPR(in, scra, scrd, label) \
1747c478bd9Sstevel@tonic-gate	SETL41(scra, HSTC_HIGH);	\
1757c478bd9Sstevel@tonic-gate	srlx	in, 32, scrd;		\
1767c478bd9Sstevel@tonic-gate	stxa	scrd, [scra]ASI_IO;	\
1777c478bd9Sstevel@tonic-gate	dec	HST_DIFF, scra;		\
1787c478bd9Sstevel@tonic-gate	stxa	in, [scra]ASI_IO
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate#else	/* !CHEETAH && !HUMMINGBIRD */
1817c478bd9Sstevel@tonic-gate
1827c478bd9Sstevel@tonic-gate#define	GET_NATIVE_TIME(out, scr1, scr2) \
1837c478bd9Sstevel@tonic-gate	rdpr	%tick, out
1847c478bd9Sstevel@tonic-gate#define	DELTA_NATIVE_TIME(delta, reg, scr1, scr2, scr3) \
1857c478bd9Sstevel@tonic-gate	rdpr	%tick, reg;		\
1867c478bd9Sstevel@tonic-gate	add	reg, delta, reg;	\
1877c478bd9Sstevel@tonic-gate	wrpr	reg, %tick
1887c478bd9Sstevel@tonic-gate#define	RD_TICKCMPR(out, scr)		\
1897c478bd9Sstevel@tonic-gate	rd	TICK_COMPARE, out
1907c478bd9Sstevel@tonic-gate#ifdef BB_ERRATA_1 /* writes to TICK_COMPARE may fail */
1917c478bd9Sstevel@tonic-gate/*
1927c478bd9Sstevel@tonic-gate * Writes to the TICK_COMPARE register sometimes fail on blackbird modules.
1937c478bd9Sstevel@tonic-gate * The failure occurs only when the following instruction decodes to wr or
1947c478bd9Sstevel@tonic-gate * wrpr.  The workaround is to immediately follow writes to TICK_COMPARE
1957c478bd9Sstevel@tonic-gate * with a read, thus stalling the pipe and keeping following instructions
1967c478bd9Sstevel@tonic-gate * from causing data corruption.  Aligning to a quadword will ensure these
1977c478bd9Sstevel@tonic-gate * two instructions are not split due to i$ misses.
1987c478bd9Sstevel@tonic-gate */
1997c478bd9Sstevel@tonic-gate#define WR_TICKCMPR(cmpr,scr1,scr2,label)	\
2007c478bd9Sstevel@tonic-gate	ba,a	.bb_errata_1.label		;\
2017c478bd9Sstevel@tonic-gate	.align	64				;\
2027c478bd9Sstevel@tonic-gate.bb_errata_1.label:				;\
2037c478bd9Sstevel@tonic-gate	wr	cmpr, TICK_COMPARE		;\
2047c478bd9Sstevel@tonic-gate	rd	TICK_COMPARE, %g0
2057c478bd9Sstevel@tonic-gate#else	/* BB_ERRATA_1 */
2067c478bd9Sstevel@tonic-gate#define	WR_TICKCMPR(in,scr1,scr2,label)		\
2077c478bd9Sstevel@tonic-gate	wr	in, TICK_COMPARE
2087c478bd9Sstevel@tonic-gate#endif	/* BB_ERRATA_1 */
2097c478bd9Sstevel@tonic-gate
2107c478bd9Sstevel@tonic-gate#endif	/* !CHEETAH && !HUMMINGBIRD */
2117c478bd9Sstevel@tonic-gate
2127c478bd9Sstevel@tonic-gate#include <sys/clock.h>
2137c478bd9Sstevel@tonic-gate
2147c478bd9Sstevel@tonic-gate
2157c478bd9Sstevel@tonic-gate#include <sys/asm_linkage.h>
2167c478bd9Sstevel@tonic-gate#include <sys/privregs.h>
2177c478bd9Sstevel@tonic-gate#include <sys/machparam.h>	/* To get SYSBASE and PAGESIZE */
2187c478bd9Sstevel@tonic-gate#include <sys/machthread.h>
2197c478bd9Sstevel@tonic-gate#include <sys/clock.h>
2207c478bd9Sstevel@tonic-gate#include <sys/intreg.h>
2217c478bd9Sstevel@tonic-gate#include <sys/psr_compat.h>
2227c478bd9Sstevel@tonic-gate#include <sys/isa_defs.h>
2237c478bd9Sstevel@tonic-gate#include <sys/dditypes.h>
2247c478bd9Sstevel@tonic-gate#include <sys/intr.h>
2257c478bd9Sstevel@tonic-gate
2267c478bd9Sstevel@tonic-gate#include "assym.h"
2277c478bd9Sstevel@tonic-gate
2287c478bd9Sstevel@tonic-gate	ENTRY(get_impl)
2297c478bd9Sstevel@tonic-gate	GET_CPU_IMPL(%o0)
2307c478bd9Sstevel@tonic-gate	retl
2317c478bd9Sstevel@tonic-gate	nop
2327c478bd9Sstevel@tonic-gate	SET_SIZE(get_impl)
2337c478bd9Sstevel@tonic-gate
2347c478bd9Sstevel@tonic-gate/*
2359b0bb795SJohn Levon * Softint generated when counter field of tick reg matches value field
2367c478bd9Sstevel@tonic-gate * of tick_cmpr reg
2377c478bd9Sstevel@tonic-gate */
2387c478bd9Sstevel@tonic-gate	ENTRY_NP(tickcmpr_set)
2397c478bd9Sstevel@tonic-gate	! get 64-bit clock_cycles interval
2407c478bd9Sstevel@tonic-gate	mov	%o0, %o2
2417c478bd9Sstevel@tonic-gate	mov	8, %o3			! A reasonable initial step size
2427c478bd9Sstevel@tonic-gate1:
2437c478bd9Sstevel@tonic-gate	WR_TICKCMPR(%o2,%o4,%o5,__LINE__)	! Write to TICK_CMPR
2447c478bd9Sstevel@tonic-gate
2457c478bd9Sstevel@tonic-gate	GET_NATIVE_TIME(%o0, %o4, %o5)	! Read %tick to confirm the
2467c478bd9Sstevel@tonic-gate	sllx	%o0, 1, %o0		!   value we wrote was in the future.
2477c478bd9Sstevel@tonic-gate	srlx	%o0, 1, %o0
2487c478bd9Sstevel@tonic-gate
2497c478bd9Sstevel@tonic-gate	cmp	%o2, %o0		! If the value we wrote was in the
2507c478bd9Sstevel@tonic-gate	bg,pt	%xcc, 2f		!   future, then blow out of here.
2517c478bd9Sstevel@tonic-gate	sllx	%o3, 1, %o3		! If not, then double our step size,
2527c478bd9Sstevel@tonic-gate	ba,pt	%xcc, 1b		!   and take another lap.
2537c478bd9Sstevel@tonic-gate	add	%o0, %o3, %o2		!
2547c478bd9Sstevel@tonic-gate2:
2557c478bd9Sstevel@tonic-gate	retl
2567c478bd9Sstevel@tonic-gate	nop
2577c478bd9Sstevel@tonic-gate	SET_SIZE(tickcmpr_set)
2587c478bd9Sstevel@tonic-gate
2597c478bd9Sstevel@tonic-gate	ENTRY_NP(tickcmpr_disable)
2607c478bd9Sstevel@tonic-gate	mov	1, %g1
2617c478bd9Sstevel@tonic-gate	sllx	%g1, TICKINT_DIS_SHFT, %o0
2627c478bd9Sstevel@tonic-gate	WR_TICKCMPR(%o0,%o4,%o5,__LINE__)	! Write to TICK_CMPR
2637c478bd9Sstevel@tonic-gate	retl
2647c478bd9Sstevel@tonic-gate	nop
2657c478bd9Sstevel@tonic-gate	SET_SIZE(tickcmpr_disable)
2667c478bd9Sstevel@tonic-gate
2679b0bb795SJohn Levon#ifdef DEBUG
2689b0bb795SJohn Levon	.seg	".text"
2699b0bb795SJohn Levontick_write_panic:
2709b0bb795SJohn Levon	.asciz	"tick_write_delta: interrupts already disabled on entry"
2719b0bb795SJohn Levon#endif	/* DEBUG */
2727c478bd9Sstevel@tonic-gate
2737c478bd9Sstevel@tonic-gate/*
2747c478bd9Sstevel@tonic-gate * tick_write_delta() increments %tick by the specified delta.  This should
2757c478bd9Sstevel@tonic-gate * only be called after a CPR event to assure that gethrtime() continues to
2767c478bd9Sstevel@tonic-gate * increase monotonically.  Obviously, writing %tick needs to de done very
2777c478bd9Sstevel@tonic-gate * carefully to avoid introducing unnecessary %tick skew across CPUs.  For
2787c478bd9Sstevel@tonic-gate * this reason, we make sure we're i-cache hot before actually writing to
2797c478bd9Sstevel@tonic-gate * %tick.
2807c478bd9Sstevel@tonic-gate */
2817c478bd9Sstevel@tonic-gate	ENTRY_NP(tick_write_delta)
2827c478bd9Sstevel@tonic-gate	rdpr	%pstate, %g1
2837c478bd9Sstevel@tonic-gate#ifdef DEBUG
2847c478bd9Sstevel@tonic-gate	andcc	%g1, PSTATE_IE, %g0	! If DEBUG, check that interrupts
2857c478bd9Sstevel@tonic-gate	bnz	0f			! aren't already disabled.
2867c478bd9Sstevel@tonic-gate	sethi	%hi(tick_write_panic), %o1
2877c478bd9Sstevel@tonic-gate        save    %sp, -SA(MINFRAME), %sp ! get a new window to preserve caller
2887c478bd9Sstevel@tonic-gate	call	panic
2897c478bd9Sstevel@tonic-gate	or	%i1, %lo(tick_write_panic), %o0
2907c478bd9Sstevel@tonic-gate#endif	/* DEBUG */
2917c478bd9Sstevel@tonic-gate0:	wrpr	%g1, PSTATE_IE, %pstate	! Disable interrupts
2927c478bd9Sstevel@tonic-gate	mov	%o0, %o2
2937c478bd9Sstevel@tonic-gate	ba	0f			! Branch to cache line-aligned instr.
2947c478bd9Sstevel@tonic-gate	nop
2957c478bd9Sstevel@tonic-gate	.align	16
2967c478bd9Sstevel@tonic-gate0:	nop				! The next 3 instructions are now hot.
2977c478bd9Sstevel@tonic-gate	DELTA_NATIVE_TIME(%o2, %o3, %o4, %o5, %g2)	! read/inc/write %tick
2987c478bd9Sstevel@tonic-gate
2997c478bd9Sstevel@tonic-gate	retl				! Return
3007c478bd9Sstevel@tonic-gate	wrpr	%g0, %g1, %pstate	!     delay: Re-enable interrupts
3017c478bd9Sstevel@tonic-gate
3027c478bd9Sstevel@tonic-gate	ENTRY_NP(tickcmpr_disabled)
3037c478bd9Sstevel@tonic-gate	RD_TICKCMPR(%g1, %o0)
3047c478bd9Sstevel@tonic-gate	retl
3057c478bd9Sstevel@tonic-gate	srlx	%g1, TICKINT_DIS_SHFT, %o0
3067c478bd9Sstevel@tonic-gate	SET_SIZE(tickcmpr_disabled)
3077c478bd9Sstevel@tonic-gate
3087c478bd9Sstevel@tonic-gate/*
3097c478bd9Sstevel@tonic-gate * Get current tick
3107c478bd9Sstevel@tonic-gate */
3117c478bd9Sstevel@tonic-gate
3127c478bd9Sstevel@tonic-gate	ENTRY(gettick)
313b52a336eSPavel Tatashin	ALTENTRY(randtick)
3147c478bd9Sstevel@tonic-gate	GET_NATIVE_TIME(%o0, %o2, %o3)
3157c478bd9Sstevel@tonic-gate	retl
3167c478bd9Sstevel@tonic-gate	nop
317b52a336eSPavel Tatashin	SET_SIZE(randtick)
3187c478bd9Sstevel@tonic-gate	SET_SIZE(gettick)
3197c478bd9Sstevel@tonic-gate
3207c478bd9Sstevel@tonic-gate
3217c478bd9Sstevel@tonic-gate/*
3227c478bd9Sstevel@tonic-gate * Return the counter portion of the tick register.
3237c478bd9Sstevel@tonic-gate */
3247c478bd9Sstevel@tonic-gate
3257c478bd9Sstevel@tonic-gate	ENTRY_NP(gettick_counter)
3267c478bd9Sstevel@tonic-gate	rdpr	%tick, %o0
3277c478bd9Sstevel@tonic-gate	sllx	%o0, 1, %o0
3287c478bd9Sstevel@tonic-gate	retl
3297c478bd9Sstevel@tonic-gate	srlx	%o0, 1, %o0		! shake off npt bit
3307c478bd9Sstevel@tonic-gate	SET_SIZE(gettick_counter)
3317c478bd9Sstevel@tonic-gate
3327c478bd9Sstevel@tonic-gate/*
3337c478bd9Sstevel@tonic-gate * Provide a C callable interface to the trap that reads the hi-res timer.
3347c478bd9Sstevel@tonic-gate * Returns 64-bit nanosecond timestamp in %o0 and %o1.
3357c478bd9Sstevel@tonic-gate */
3367c478bd9Sstevel@tonic-gate
3377c478bd9Sstevel@tonic-gate	ENTRY_NP(gethrtime)
3387c478bd9Sstevel@tonic-gate	GET_HRTIME(%g1, %o0, %o1, %o2, %o3, %o4, %o5, %g2)
3397c478bd9Sstevel@tonic-gate							! %g1 = hrtime
3407c478bd9Sstevel@tonic-gate	retl
3417c478bd9Sstevel@tonic-gate	mov	%g1, %o0
3427c478bd9Sstevel@tonic-gate	SET_SIZE(gethrtime)
3437c478bd9Sstevel@tonic-gate
3447c478bd9Sstevel@tonic-gate	ENTRY_NP(gethrtime_unscaled)
3457c478bd9Sstevel@tonic-gate	GET_NATIVE_TIME(%g1, %o2, %o3)			! %g1 = native time
3467c478bd9Sstevel@tonic-gate	retl
3477c478bd9Sstevel@tonic-gate	mov	%g1, %o0
3487c478bd9Sstevel@tonic-gate	SET_SIZE(gethrtime_unscaled)
3497c478bd9Sstevel@tonic-gate
3507c478bd9Sstevel@tonic-gate	ENTRY_NP(gethrtime_waitfree)
3517c478bd9Sstevel@tonic-gate	ALTENTRY(dtrace_gethrtime)
3527c478bd9Sstevel@tonic-gate	GET_NATIVE_TIME(%g1, %o2, %o3)			! %g1 = native time
3537c478bd9Sstevel@tonic-gate	NATIVE_TIME_TO_NSEC(%g1, %o2, %o3)
3547c478bd9Sstevel@tonic-gate	retl
3557c478bd9Sstevel@tonic-gate	mov	%g1, %o0
3567c478bd9Sstevel@tonic-gate	SET_SIZE(dtrace_gethrtime)
3577c478bd9Sstevel@tonic-gate	SET_SIZE(gethrtime_waitfree)
3587c478bd9Sstevel@tonic-gate
3597c478bd9Sstevel@tonic-gate	ENTRY(gethrtime_max)
3607c478bd9Sstevel@tonic-gate	NATIVE_TIME_MAX(%g1)
3617c478bd9Sstevel@tonic-gate	NATIVE_TIME_TO_NSEC(%g1, %o0, %o1)
3627c478bd9Sstevel@tonic-gate
3637c478bd9Sstevel@tonic-gate	! hrtime_t's are signed, max hrtime_t must be positive
3647c478bd9Sstevel@tonic-gate	mov	-1, %o2
3657c478bd9Sstevel@tonic-gate	brlz,a	%g1, 1f
3667c478bd9Sstevel@tonic-gate	srlx	%o2, 1, %g1
3677c478bd9Sstevel@tonic-gate1:
3687c478bd9Sstevel@tonic-gate	retl
3697c478bd9Sstevel@tonic-gate	mov	%g1, %o0
3707c478bd9Sstevel@tonic-gate	SET_SIZE(gethrtime_max)
3717c478bd9Sstevel@tonic-gate
3727c478bd9Sstevel@tonic-gate	ENTRY(scalehrtime)
3737c478bd9Sstevel@tonic-gate	ldx	[%o0], %o1
3747c478bd9Sstevel@tonic-gate	NATIVE_TIME_TO_NSEC(%o1, %o2, %o3)
3757c478bd9Sstevel@tonic-gate	retl
3767c478bd9Sstevel@tonic-gate	stx	%o1, [%o0]
3777c478bd9Sstevel@tonic-gate	SET_SIZE(scalehrtime)
3787c478bd9Sstevel@tonic-gate
3797c478bd9Sstevel@tonic-gate/*
3807c478bd9Sstevel@tonic-gate * Fast trap to return a timestamp, uses trap window, leaves traps
3817c478bd9Sstevel@tonic-gate * disabled.  Returns a 64-bit nanosecond timestamp in %o0 and %o1.
3827c478bd9Sstevel@tonic-gate *
3837c478bd9Sstevel@tonic-gate * This is the handler for the ST_GETHRTIME trap.
3847c478bd9Sstevel@tonic-gate */
3857c478bd9Sstevel@tonic-gate
3867c478bd9Sstevel@tonic-gate	ENTRY_NP(get_timestamp)
3877c478bd9Sstevel@tonic-gate	GET_HRTIME(%g1, %g2, %g3, %g4, %g5, %o0, %o1, %o2)	! %g1 = hrtime
3887c478bd9Sstevel@tonic-gate	srlx	%g1, 32, %o0				! %o0 = hi32(%g1)
3897c478bd9Sstevel@tonic-gate	srl	%g1, 0, %o1				! %o1 = lo32(%g1)
3907c478bd9Sstevel@tonic-gate	FAST_TRAP_DONE
3917c478bd9Sstevel@tonic-gate	SET_SIZE(get_timestamp)
3927c478bd9Sstevel@tonic-gate
3937c478bd9Sstevel@tonic-gate/*
3947c478bd9Sstevel@tonic-gate * Macro to convert GET_HRESTIME() bits into a timestamp.
3957c478bd9Sstevel@tonic-gate *
3967c478bd9Sstevel@tonic-gate * We use two separate macros so that the platform-dependent GET_HRESTIME()
3977c478bd9Sstevel@tonic-gate * can be as small as possible; CONV_HRESTIME() implements the generic part.
3987c478bd9Sstevel@tonic-gate */
3997c478bd9Sstevel@tonic-gate#define	CONV_HRESTIME(hrestsec, hrestnsec, adj, nslt, nano) \
4007c478bd9Sstevel@tonic-gate	brz,pt	adj, 3f;		/* no adjustments, it's easy */	\
4017c478bd9Sstevel@tonic-gate	add	hrestnsec, nslt, hrestnsec; /* hrest.tv_nsec += nslt */	\
4027c478bd9Sstevel@tonic-gate	brlz,pn	adj, 2f;		/* if hrestime_adj negative */	\
403646e55b6Scth	srlx	nslt, ADJ_SHIFT, nslt;	/* delay: nslt >>= 4 */		\
4047c478bd9Sstevel@tonic-gate	subcc	adj, nslt, %g0;		/* hrestime_adj - nslt/16 */	\
4057c478bd9Sstevel@tonic-gate	movg	%xcc, nslt, adj;	/* adj by min(adj, nslt/16) */	\
4067c478bd9Sstevel@tonic-gate	ba	3f;			/* go convert to sec/nsec */	\
4077c478bd9Sstevel@tonic-gate	add	hrestnsec, adj, hrestnsec; /* delay: apply adjustment */ \
4087c478bd9Sstevel@tonic-gate2:	addcc	adj, nslt, %g0;		/* hrestime_adj + nslt/16 */	\
4097c478bd9Sstevel@tonic-gate	bge,a,pt %xcc, 3f;		/* is adj less negative? */	\
4107c478bd9Sstevel@tonic-gate	add	hrestnsec, adj, hrestnsec; /* yes: hrest.nsec += adj */	\
4117c478bd9Sstevel@tonic-gate	sub	hrestnsec, nslt, hrestnsec; /* no: hrest.nsec -= nslt/16 */ \
4127c478bd9Sstevel@tonic-gate3:	cmp	hrestnsec, nano;	/* more than a billion? */	\
4137c478bd9Sstevel@tonic-gate	bl,pt	%xcc, 4f;		/* if not, we're done */	\
4147c478bd9Sstevel@tonic-gate	nop;				/* delay: do nothing :( */	\
4157c478bd9Sstevel@tonic-gate	add	hrestsec, 1, hrestsec;	/* hrest.tv_sec++; */		\
4167c478bd9Sstevel@tonic-gate	sub	hrestnsec, nano, hrestnsec; /* hrest.tv_nsec -= NANOSEC; */ \
417646e55b6Scth	ba,a	3b;			/* check >= billion again */	\
4187c478bd9Sstevel@tonic-gate4:
4197c478bd9Sstevel@tonic-gate
4207c478bd9Sstevel@tonic-gate	ENTRY_NP(gethrestime)
4217c478bd9Sstevel@tonic-gate	GET_HRESTIME(%o1, %o2, %o3, %o4, %o5, %g1, %g2, %g3, %g4)
4227c478bd9Sstevel@tonic-gate	CONV_HRESTIME(%o1, %o2, %o3, %o4, %o5)
4237c478bd9Sstevel@tonic-gate	stn	%o1, [%o0]
4247c478bd9Sstevel@tonic-gate	retl
4257c478bd9Sstevel@tonic-gate	stn	%o2, [%o0 + CLONGSIZE]
4267c478bd9Sstevel@tonic-gate	SET_SIZE(gethrestime)
4277c478bd9Sstevel@tonic-gate
4287c478bd9Sstevel@tonic-gate/*
4297c478bd9Sstevel@tonic-gate * Similar to gethrestime(), but gethrestime_sec() returns current hrestime
4307c478bd9Sstevel@tonic-gate * seconds.
4317c478bd9Sstevel@tonic-gate */
4327c478bd9Sstevel@tonic-gate	ENTRY_NP(gethrestime_sec)
4337c478bd9Sstevel@tonic-gate	GET_HRESTIME(%o0, %o2, %o3, %o4, %o5, %g1, %g2, %g3, %g4)
4347c478bd9Sstevel@tonic-gate	CONV_HRESTIME(%o0, %o2, %o3, %o4, %o5)
4357c478bd9Sstevel@tonic-gate	retl					! %o0 current hrestime seconds
4367c478bd9Sstevel@tonic-gate	nop
4377c478bd9Sstevel@tonic-gate	SET_SIZE(gethrestime_sec)
4387c478bd9Sstevel@tonic-gate
4397c478bd9Sstevel@tonic-gate/*
4407c478bd9Sstevel@tonic-gate * Returns the hrestime on the last tick.  This is simpler than gethrestime()
4417c478bd9Sstevel@tonic-gate * and gethrestime_sec():  no conversion is required.  gethrestime_lasttick()
4427c478bd9Sstevel@tonic-gate * follows the same locking algorithm as GET_HRESTIME and GET_HRTIME,
4437c478bd9Sstevel@tonic-gate * outlined in detail in clock.h.  (Unlike GET_HRESTIME/GET_HRTIME, we don't
4447c478bd9Sstevel@tonic-gate * rely on load dependencies to effect the membar #LoadLoad, instead declaring
4457c478bd9Sstevel@tonic-gate * it explicitly.)
4467c478bd9Sstevel@tonic-gate */
4477c478bd9Sstevel@tonic-gate	ENTRY_NP(gethrestime_lasttick)
4487c478bd9Sstevel@tonic-gate	sethi	%hi(hres_lock), %o1
4497c478bd9Sstevel@tonic-gate0:
4507c478bd9Sstevel@tonic-gate	lduw	[%o1 + %lo(hres_lock)], %o2	! Load lock value
4517c478bd9Sstevel@tonic-gate	membar	#LoadLoad			! Load of lock must complete
452*5d9d9091SRichard Lowe	andn	%o2, 1, %o2			! Mask off lowest bit
4537c478bd9Sstevel@tonic-gate	ldn	[%o1 + %lo(hrestime)], %g1	! Seconds.
4547c478bd9Sstevel@tonic-gate	add	%o1, %lo(hrestime), %o4
4557c478bd9Sstevel@tonic-gate	ldn	[%o4 + CLONGSIZE], %g2		! Nanoseconds.
4567c478bd9Sstevel@tonic-gate	membar	#LoadLoad			! All loads must complete
4577c478bd9Sstevel@tonic-gate	lduw	[%o1 + %lo(hres_lock)], %o3	! Reload lock value
4587c478bd9Sstevel@tonic-gate	cmp	%o3, %o2			! If lock is locked or has
4597c478bd9Sstevel@tonic-gate	bne	0b				!   changed, retry.
4607c478bd9Sstevel@tonic-gate	stn	%g1, [%o0]			! Delay: store seconds
4617c478bd9Sstevel@tonic-gate	retl
4627c478bd9Sstevel@tonic-gate	stn	%g2, [%o0 + CLONGSIZE]		! Delay: store nanoseconds
4637c478bd9Sstevel@tonic-gate	SET_SIZE(gethrestime_lasttick)
4647c478bd9Sstevel@tonic-gate
4657c478bd9Sstevel@tonic-gate/*
4667c478bd9Sstevel@tonic-gate * Fast trap for gettimeofday().  Returns a timestruc_t in %o0 and %o1.
4677c478bd9Sstevel@tonic-gate *
4687c478bd9Sstevel@tonic-gate * This is the handler for the ST_GETHRESTIME trap.
4697c478bd9Sstevel@tonic-gate */
4707c478bd9Sstevel@tonic-gate
4717c478bd9Sstevel@tonic-gate	ENTRY_NP(get_hrestime)
4727c478bd9Sstevel@tonic-gate	GET_HRESTIME(%o0, %o1, %g1, %g2, %g3, %g4, %g5, %o2, %o3)
4737c478bd9Sstevel@tonic-gate	CONV_HRESTIME(%o0, %o1, %g1, %g2, %g3)
4747c478bd9Sstevel@tonic-gate	FAST_TRAP_DONE
4757c478bd9Sstevel@tonic-gate	SET_SIZE(get_hrestime)
4767c478bd9Sstevel@tonic-gate
4777c478bd9Sstevel@tonic-gate/*
4787c478bd9Sstevel@tonic-gate * Fast trap to return lwp virtual time, uses trap window, leaves traps
4797c478bd9Sstevel@tonic-gate * disabled.  Returns a 64-bit number in %o0:%o1, which is the number
4807c478bd9Sstevel@tonic-gate * of nanoseconds consumed.
4817c478bd9Sstevel@tonic-gate *
4827c478bd9Sstevel@tonic-gate * This is the handler for the ST_GETHRVTIME trap.
4837c478bd9Sstevel@tonic-gate *
4847c478bd9Sstevel@tonic-gate * Register usage:
4857c478bd9Sstevel@tonic-gate *	%o0, %o1 = return lwp virtual time
4867c478bd9Sstevel@tonic-gate * 	%o2 = CPU/thread
4877c478bd9Sstevel@tonic-gate * 	%o3 = lwp
4887c478bd9Sstevel@tonic-gate * 	%g1 = scratch
4897c478bd9Sstevel@tonic-gate * 	%g5 = scratch
4907c478bd9Sstevel@tonic-gate */
4917c478bd9Sstevel@tonic-gate	ENTRY_NP(get_virtime)
4927c478bd9Sstevel@tonic-gate	GET_NATIVE_TIME(%g5, %g1, %g2)	! %g5 = native time in ticks
4937c478bd9Sstevel@tonic-gate	CPU_ADDR(%g2, %g3)			! CPU struct ptr to %g2
4947c478bd9Sstevel@tonic-gate	ldn	[%g2 + CPU_THREAD], %g2		! thread pointer to %g2
4957c478bd9Sstevel@tonic-gate	ldn	[%g2 + T_LWP], %g3		! lwp pointer to %g3
4967c478bd9Sstevel@tonic-gate
4977c478bd9Sstevel@tonic-gate	/*
4987c478bd9Sstevel@tonic-gate	 * Subtract start time of current microstate from time
4997c478bd9Sstevel@tonic-gate	 * of day to get increment for lwp virtual time.
5007c478bd9Sstevel@tonic-gate	 */
5017c478bd9Sstevel@tonic-gate	ldx	[%g3 + LWP_STATE_START], %g1	! ms_state_start
5027c478bd9Sstevel@tonic-gate	sub	%g5, %g1, %g5
5037c478bd9Sstevel@tonic-gate
5047c478bd9Sstevel@tonic-gate	/*
5057c478bd9Sstevel@tonic-gate	 * Add current value of ms_acct[LMS_USER]
5067c478bd9Sstevel@tonic-gate	 */
5077c478bd9Sstevel@tonic-gate	ldx	[%g3 + LWP_ACCT_USER], %g1	! ms_acct[LMS_USER]
5087c478bd9Sstevel@tonic-gate	add	%g5, %g1, %g5
509*5d9d9091SRichard Lowe	NATIVE_TIME_TO_NSEC(%g5, %g1, %o0)
510*5d9d9091SRichard Lowe
5117c478bd9Sstevel@tonic-gate	srl	%g5, 0, %o1			! %o1 = lo32(%g5)
5127c478bd9Sstevel@tonic-gate	srlx	%g5, 32, %o0			! %o0 = hi32(%g5)
5137c478bd9Sstevel@tonic-gate
5147c478bd9Sstevel@tonic-gate	FAST_TRAP_DONE
5157c478bd9Sstevel@tonic-gate	SET_SIZE(get_virtime)
5167c478bd9Sstevel@tonic-gate
5177c478bd9Sstevel@tonic-gate
5187c478bd9Sstevel@tonic-gate
5197c478bd9Sstevel@tonic-gate	.seg	".text"
5207c478bd9Sstevel@tonic-gatehrtime_base_panic:
5217c478bd9Sstevel@tonic-gate	.asciz	"hrtime_base stepping back"
5227c478bd9Sstevel@tonic-gate
5237c478bd9Sstevel@tonic-gate
5247c478bd9Sstevel@tonic-gate	ENTRY_NP(hres_tick)
5257c478bd9Sstevel@tonic-gate	save	%sp, -SA(MINFRAME), %sp	! get a new window
5267c478bd9Sstevel@tonic-gate
5277c478bd9Sstevel@tonic-gate	sethi	%hi(hrestime), %l4
5287c478bd9Sstevel@tonic-gate	ldstub	[%l4 + %lo(hres_lock + HRES_LOCK_OFFSET)], %l5	! try locking
5297c478bd9Sstevel@tonic-gate7:	tst	%l5
5307c478bd9Sstevel@tonic-gate	bz,pt	%xcc, 8f			! if we got it, drive on
5317c478bd9Sstevel@tonic-gate	ld	[%l4 + %lo(nsec_scale)], %l5	! delay: %l5 = scaling factor
5327c478bd9Sstevel@tonic-gate	ldub	[%l4 + %lo(hres_lock + HRES_LOCK_OFFSET)], %l5
5337c478bd9Sstevel@tonic-gate9:	tst	%l5
5347c478bd9Sstevel@tonic-gate	bz,a,pn	%xcc, 7b
5357c478bd9Sstevel@tonic-gate	ldstub	[%l4 + %lo(hres_lock + HRES_LOCK_OFFSET)], %l5
5367c478bd9Sstevel@tonic-gate	ba,pt	%xcc, 9b
5377c478bd9Sstevel@tonic-gate	ldub	[%l4 + %lo(hres_lock + HRES_LOCK_OFFSET)], %l5
5387c478bd9Sstevel@tonic-gate8:
5397c478bd9Sstevel@tonic-gate	membar	#StoreLoad|#StoreStore
5407c478bd9Sstevel@tonic-gate
5417c478bd9Sstevel@tonic-gate	!
5427c478bd9Sstevel@tonic-gate	! update hres_last_tick.  %l5 has the scaling factor (nsec_scale).
5437c478bd9Sstevel@tonic-gate	!
5447c478bd9Sstevel@tonic-gate	ldx	[%l4 + %lo(hrtime_base)], %g1	! load current hrtime_base
5457c478bd9Sstevel@tonic-gate	GET_NATIVE_TIME(%l0, %l3, %l6)		! current native time
5467c478bd9Sstevel@tonic-gate	stx	%l0, [%l4 + %lo(hres_last_tick)]! prev = current
5477c478bd9Sstevel@tonic-gate	! convert native time to nsecs
5487c478bd9Sstevel@tonic-gate	NATIVE_TIME_TO_NSEC_SCALE(%l0, %l5, %l2, NSEC_SHIFT)
5497c478bd9Sstevel@tonic-gate
5507c478bd9Sstevel@tonic-gate	sub	%l0, %g1, %i1			! get accurate nsec delta
5517c478bd9Sstevel@tonic-gate
552*5d9d9091SRichard Lowe	ldx	[%l4 + %lo(hrtime_base)], %l1
5537c478bd9Sstevel@tonic-gate	cmp	%l1, %l0
5547c478bd9Sstevel@tonic-gate	bg,pn	%xcc, 9f
5557c478bd9Sstevel@tonic-gate	nop
5567c478bd9Sstevel@tonic-gate
5577c478bd9Sstevel@tonic-gate	stx	%l0, [%l4 + %lo(hrtime_base)]	! update hrtime_base
5587c478bd9Sstevel@tonic-gate
5597c478bd9Sstevel@tonic-gate	!
5607c478bd9Sstevel@tonic-gate	! apply adjustment, if any
5617c478bd9Sstevel@tonic-gate	!
5627c478bd9Sstevel@tonic-gate	ldx	[%l4 + %lo(hrestime_adj)], %l0	! %l0 = hrestime_adj
5637c478bd9Sstevel@tonic-gate	brz	%l0, 2f
5647c478bd9Sstevel@tonic-gate						! hrestime_adj == 0 ?
5657c478bd9Sstevel@tonic-gate						! yes, skip adjustments
5667c478bd9Sstevel@tonic-gate	clr	%l5				! delay: set adj to zero
5677c478bd9Sstevel@tonic-gate	tst	%l0				! is hrestime_adj >= 0 ?
5687c478bd9Sstevel@tonic-gate	bge,pt	%xcc, 1f			! yes, go handle positive case
5697c478bd9Sstevel@tonic-gate	srl	%i1, ADJ_SHIFT, %l5		! delay: %l5 = adj
5707c478bd9Sstevel@tonic-gate
5717c478bd9Sstevel@tonic-gate	addcc	%l0, %l5, %g0			! hrestime_adj < -adj ?
5727c478bd9Sstevel@tonic-gate	bl,pt	%xcc, 2f			! yes, use current adj
5737c478bd9Sstevel@tonic-gate	neg	%l5				! delay: %l5 = -adj
5747c478bd9Sstevel@tonic-gate	ba,pt	%xcc, 2f
5757c478bd9Sstevel@tonic-gate	mov	%l0, %l5			! no, so set adj = hrestime_adj
5767c478bd9Sstevel@tonic-gate1:
5777c478bd9Sstevel@tonic-gate	subcc	%l0, %l5, %g0			! hrestime_adj < adj ?
5787c478bd9Sstevel@tonic-gate	bl,a,pt	%xcc, 2f			! yes, set adj = hrestime_adj
5797c478bd9Sstevel@tonic-gate	mov	%l0, %l5			! delay: adj = hrestime_adj
5807c478bd9Sstevel@tonic-gate2:
5817c478bd9Sstevel@tonic-gate	ldx	[%l4 + %lo(timedelta)], %l0	! %l0 = timedelta
5827c478bd9Sstevel@tonic-gate	sub	%l0, %l5, %l0			! timedelta -= adj
5837c478bd9Sstevel@tonic-gate
5847c478bd9Sstevel@tonic-gate	stx	%l0, [%l4 + %lo(timedelta)]	! store new timedelta
5857c478bd9Sstevel@tonic-gate	stx	%l0, [%l4 + %lo(hrestime_adj)]	! hrestime_adj = timedelta
5867c478bd9Sstevel@tonic-gate
5877c478bd9Sstevel@tonic-gate	or	%l4, %lo(hrestime), %l2
5887c478bd9Sstevel@tonic-gate	ldn	[%l2], %i2			! %i2:%i3 = hrestime sec:nsec
5897c478bd9Sstevel@tonic-gate	ldn	[%l2 + CLONGSIZE], %i3
5907c478bd9Sstevel@tonic-gate	add	%i3, %l5, %i3			! hrestime.nsec += adj
5917c478bd9Sstevel@tonic-gate	add	%i3, %i1, %i3			! hrestime.nsec += nslt
5927c478bd9Sstevel@tonic-gate
5937c478bd9Sstevel@tonic-gate	set	NANOSEC, %l5			! %l5 = NANOSEC
5947c478bd9Sstevel@tonic-gate	cmp	%i3, %l5
5957c478bd9Sstevel@tonic-gate	bl,pt	%xcc, 5f			! if hrestime.tv_nsec < NANOSEC
5967c478bd9Sstevel@tonic-gate	sethi	%hi(one_sec), %i1		! delay
5977c478bd9Sstevel@tonic-gate	add	%i2, 0x1, %i2			! hrestime.tv_sec++
5987c478bd9Sstevel@tonic-gate	sub	%i3, %l5, %i3			! hrestime.tv_nsec - NANOSEC
5997c478bd9Sstevel@tonic-gate	mov	0x1, %l5
6007c478bd9Sstevel@tonic-gate	st	%l5, [%i1 + %lo(one_sec)]
6017c478bd9Sstevel@tonic-gate5:
6027c478bd9Sstevel@tonic-gate	stn	%i2, [%l2]
6037c478bd9Sstevel@tonic-gate	stn	%i3, [%l2 + CLONGSIZE]		! store the new hrestime
6047c478bd9Sstevel@tonic-gate
6057c478bd9Sstevel@tonic-gate	membar	#StoreStore
6067c478bd9Sstevel@tonic-gate
6077c478bd9Sstevel@tonic-gate	ld	[%l4 + %lo(hres_lock)], %i1
6087c478bd9Sstevel@tonic-gate	inc	%i1				! release lock
6097c478bd9Sstevel@tonic-gate	st	%i1, [%l4 + %lo(hres_lock)]	! clear hres_lock
6107c478bd9Sstevel@tonic-gate
6117c478bd9Sstevel@tonic-gate	ret
6127c478bd9Sstevel@tonic-gate	restore
6137c478bd9Sstevel@tonic-gate
6147c478bd9Sstevel@tonic-gate9:
6157c478bd9Sstevel@tonic-gate	!
6167c478bd9Sstevel@tonic-gate	! release hres_lock
6177c478bd9Sstevel@tonic-gate	!
6187c478bd9Sstevel@tonic-gate	ld	[%l4 + %lo(hres_lock)], %i1
6197c478bd9Sstevel@tonic-gate	inc	%i1
6207c478bd9Sstevel@tonic-gate	st	%i1, [%l4 + %lo(hres_lock)]
6217c478bd9Sstevel@tonic-gate
6227c478bd9Sstevel@tonic-gate	sethi	%hi(hrtime_base_panic), %o0
6237c478bd9Sstevel@tonic-gate	call	panic
6247c478bd9Sstevel@tonic-gate	or	%o0, %lo(hrtime_base_panic), %o0
6257c478bd9Sstevel@tonic-gate
6267c478bd9Sstevel@tonic-gate	SET_SIZE(hres_tick)
6277c478bd9Sstevel@tonic-gate
6287c478bd9Sstevel@tonic-gate	.seg	".text"
6297c478bd9Sstevel@tonic-gatekstat_q_panic_msg:
6307c478bd9Sstevel@tonic-gate	.asciz	"kstat_q_exit: qlen == 0"
6317c478bd9Sstevel@tonic-gate
6327c478bd9Sstevel@tonic-gate	ENTRY(kstat_q_panic)
6337c478bd9Sstevel@tonic-gate	save	%sp, -SA(MINFRAME), %sp
6347c478bd9Sstevel@tonic-gate	sethi	%hi(kstat_q_panic_msg), %o0
6357c478bd9Sstevel@tonic-gate	call	panic
6367c478bd9Sstevel@tonic-gate	or	%o0, %lo(kstat_q_panic_msg), %o0
6377c478bd9Sstevel@tonic-gate	/*NOTREACHED*/
6387c478bd9Sstevel@tonic-gate	SET_SIZE(kstat_q_panic)
6397c478bd9Sstevel@tonic-gate
6407c478bd9Sstevel@tonic-gate#define	BRZPN	brz,pn
6417c478bd9Sstevel@tonic-gate#define	BRZPT	brz,pt
6427c478bd9Sstevel@tonic-gate
6437c478bd9Sstevel@tonic-gate#define	KSTAT_Q_UPDATE(QOP, QBR, QZERO, QRETURN, QTYPE) \
644*5d9d9091SRichard Lowe	ld	[%o0 + QTYPE##CNT], %o1;	/* %o1 = old qlen */	\
6457c478bd9Sstevel@tonic-gate	QOP	%o1, 1, %o2;			/* %o2 = new qlen */	\
6467c478bd9Sstevel@tonic-gate	QBR	%o1, QZERO;			/* done if qlen == 0 */	\
647*5d9d9091SRichard Lowe	st	%o2, [%o0 + QTYPE##CNT];	/* delay: save qlen */	\
648*5d9d9091SRichard Lowe	ldx	[%o0 + QTYPE##LASTUPDATE], %o3;			\
649*5d9d9091SRichard Lowe	ldx	[%o0 + QTYPE##TIME], %o4;	/* %o4 = old time */	\
650*5d9d9091SRichard Lowe	ldx	[%o0 + QTYPE##LENTIME], %o5;	/* %o5 = old lentime */	\
6517c478bd9Sstevel@tonic-gate	sub	%g1, %o3, %o2;			/* %o2 = time delta */	\
6527c478bd9Sstevel@tonic-gate	mulx	%o1, %o2, %o3;			/* %o3 = cur lentime */	\
6537c478bd9Sstevel@tonic-gate	add	%o4, %o2, %o4;			/* %o4 = new time */	\
6547c478bd9Sstevel@tonic-gate	add	%o5, %o3, %o5;			/* %o5 = new lentime */	\
655*5d9d9091SRichard Lowe	stx	%o4, [%o0 + QTYPE##TIME];	/* save time */		\
656*5d9d9091SRichard Lowe	stx	%o5, [%o0 + QTYPE##LENTIME];	/* save lentime */	\
6577c478bd9Sstevel@tonic-gateQRETURN;								\
658*5d9d9091SRichard Lowe	stx	%g1, [%o0 + QTYPE##LASTUPDATE]; /* lastupdate = now */
6597c478bd9Sstevel@tonic-gate
6606e7bd672SToomas Soome#if !defined(DEBUG)
6616e7bd672SToomas Soome/*
6626e7bd672SToomas Soome * same as KSTAT_Q_UPDATE but without:
6636e7bd672SToomas Soome * QBR     %o1, QZERO;
6646e7bd672SToomas Soome * to be used only with non-debug build. mimics ASSERT() behaviour.
6656e7bd672SToomas Soome */
6666e7bd672SToomas Soome#define	KSTAT_Q_UPDATE_ND(QOP, QRETURN, QTYPE) \
667*5d9d9091SRichard Lowe	ld	[%o0 + QTYPE##CNT], %o1;	/* %o1 = old qlen */	\
6686e7bd672SToomas Soome	QOP	%o1, 1, %o2;			/* %o2 = new qlen */	\
669*5d9d9091SRichard Lowe	st	%o2, [%o0 + QTYPE##CNT];	/* delay: save qlen */	\
670*5d9d9091SRichard Lowe	ldx	[%o0 + QTYPE##LASTUPDATE], %o3;			\
671*5d9d9091SRichard Lowe	ldx	[%o0 + QTYPE##TIME], %o4;	/* %o4 = old time */	\
672*5d9d9091SRichard Lowe	ldx	[%o0 + QTYPE##LENTIME], %o5;	/* %o5 = old lentime */	\
6736e7bd672SToomas Soome	sub	%g1, %o3, %o2;			/* %o2 = time delta */	\
6746e7bd672SToomas Soome	mulx	%o1, %o2, %o3;			/* %o3 = cur lentime */	\
6756e7bd672SToomas Soome	add	%o4, %o2, %o4;			/* %o4 = new time */	\
6766e7bd672SToomas Soome	add	%o5, %o3, %o5;			/* %o5 = new lentime */	\
677*5d9d9091SRichard Lowe	stx	%o4, [%o0 + QTYPE##TIME];	/* save time */		\
678*5d9d9091SRichard Lowe	stx	%o5, [%o0 + QTYPE##LENTIME];	/* save lentime */	\
6796e7bd672SToomas SoomeQRETURN;								\
680*5d9d9091SRichard Lowe	stx	%g1, [%o0 + QTYPE##LASTUPDATE]; /* lastupdate = now */
6816e7bd672SToomas Soome#endif
6826e7bd672SToomas Soome
6837c478bd9Sstevel@tonic-gate	.align 16
6847c478bd9Sstevel@tonic-gate	ENTRY(kstat_waitq_enter)
6857c478bd9Sstevel@tonic-gate	GET_NATIVE_TIME(%g1, %g2, %g3)
6867c478bd9Sstevel@tonic-gate	KSTAT_Q_UPDATE(add, BRZPT, 1f, 1:retl, KSTAT_IO_W)
6877c478bd9Sstevel@tonic-gate	SET_SIZE(kstat_waitq_enter)
6887c478bd9Sstevel@tonic-gate
6897c478bd9Sstevel@tonic-gate	.align 16
6907c478bd9Sstevel@tonic-gate	ENTRY(kstat_waitq_exit)
6917c478bd9Sstevel@tonic-gate	GET_NATIVE_TIME(%g1, %g2, %g3)
6926e7bd672SToomas Soome#if defined(DEBUG)
6937c478bd9Sstevel@tonic-gate	KSTAT_Q_UPDATE(sub, BRZPN, kstat_q_panic, retl, KSTAT_IO_W)
6946e7bd672SToomas Soome#else
6956e7bd672SToomas Soome	KSTAT_Q_UPDATE_ND(sub, retl, KSTAT_IO_W)
6966e7bd672SToomas Soome#endif
6977c478bd9Sstevel@tonic-gate	SET_SIZE(kstat_waitq_exit)
6987c478bd9Sstevel@tonic-gate
6997c478bd9Sstevel@tonic-gate	.align 16
7007c478bd9Sstevel@tonic-gate	ENTRY(kstat_runq_enter)
7017c478bd9Sstevel@tonic-gate	GET_NATIVE_TIME(%g1, %g2, %g3)
7027c478bd9Sstevel@tonic-gate	KSTAT_Q_UPDATE(add, BRZPT, 1f, 1:retl, KSTAT_IO_R)
7037c478bd9Sstevel@tonic-gate	SET_SIZE(kstat_runq_enter)
7047c478bd9Sstevel@tonic-gate
7057c478bd9Sstevel@tonic-gate	.align 16
7067c478bd9Sstevel@tonic-gate	ENTRY(kstat_runq_exit)
7077c478bd9Sstevel@tonic-gate	GET_NATIVE_TIME(%g1, %g2, %g3)
7086e7bd672SToomas Soome#if defined(DEBUG)
7097c478bd9Sstevel@tonic-gate	KSTAT_Q_UPDATE(sub, BRZPN, kstat_q_panic, retl, KSTAT_IO_R)
7106e7bd672SToomas Soome#else
7116e7bd672SToomas Soome	KSTAT_Q_UPDATE_ND(sub, retl, KSTAT_IO_R)
7126e7bd672SToomas Soome#endif
7137c478bd9Sstevel@tonic-gate	SET_SIZE(kstat_runq_exit)
7147c478bd9Sstevel@tonic-gate
7157c478bd9Sstevel@tonic-gate	.align 16
7167c478bd9Sstevel@tonic-gate	ENTRY(kstat_waitq_to_runq)
7177c478bd9Sstevel@tonic-gate	GET_NATIVE_TIME(%g1, %g2, %g3)
7186e7bd672SToomas Soome#if defined(DEBUG)
7197c478bd9Sstevel@tonic-gate	KSTAT_Q_UPDATE(sub, BRZPN, kstat_q_panic, 1:, KSTAT_IO_W)
7206e7bd672SToomas Soome#else
7216e7bd672SToomas Soome	KSTAT_Q_UPDATE_ND(sub, 1:, KSTAT_IO_W)
7226e7bd672SToomas Soome#endif
7237c478bd9Sstevel@tonic-gate	KSTAT_Q_UPDATE(add, BRZPT, 1f, 1:retl, KSTAT_IO_R)
7247c478bd9Sstevel@tonic-gate	SET_SIZE(kstat_waitq_to_runq)
7257c478bd9Sstevel@tonic-gate
7267c478bd9Sstevel@tonic-gate	.align 16
7277c478bd9Sstevel@tonic-gate	ENTRY(kstat_runq_back_to_waitq)
7287c478bd9Sstevel@tonic-gate	GET_NATIVE_TIME(%g1, %g2, %g3)
7296e7bd672SToomas Soome#if defined(DEBUG)
7307c478bd9Sstevel@tonic-gate	KSTAT_Q_UPDATE(sub, BRZPN, kstat_q_panic, 1:, KSTAT_IO_R)
7316e7bd672SToomas Soome#else
7326e7bd672SToomas Soome	KSTAT_Q_UPDATE_ND(sub, 1:, KSTAT_IO_R)
7336e7bd672SToomas Soome#endif
7347c478bd9Sstevel@tonic-gate	KSTAT_Q_UPDATE(add, BRZPT, 1f, 1:retl, KSTAT_IO_W)
7357c478bd9Sstevel@tonic-gate	SET_SIZE(kstat_runq_back_to_waitq)
7367c478bd9Sstevel@tonic-gate
7377c478bd9Sstevel@tonic-gate	/*
7387c478bd9Sstevel@tonic-gate	 *  -- WARNING --
7397c478bd9Sstevel@tonic-gate	 *
7407c478bd9Sstevel@tonic-gate	 * The following variables MUST be together on a 128-byte boundary.
7417c478bd9Sstevel@tonic-gate	 * In addition to the primary performance motivation (having them all
7427c478bd9Sstevel@tonic-gate	 * on the same cache line(s)), code here and in the GET*TIME() macros
7437c478bd9Sstevel@tonic-gate	 * assumes that they all have the same high 22 address bits (so
7447c478bd9Sstevel@tonic-gate	 * there's only one sethi).
7457c478bd9Sstevel@tonic-gate	 */
7467c478bd9Sstevel@tonic-gate	.seg	".data"
7477c478bd9Sstevel@tonic-gate	.global	timedelta, hres_last_tick, hrestime, hrestime_adj
7487c478bd9Sstevel@tonic-gate	.global	hres_lock, nsec_scale, hrtime_base, traptrace_use_stick
7497c478bd9Sstevel@tonic-gate	.global	nsec_shift, adj_shift
7507c478bd9Sstevel@tonic-gate
7517c478bd9Sstevel@tonic-gate	/* XXX - above comment claims 128-bytes is necessary */
7527c478bd9Sstevel@tonic-gate	.align	64
7537c478bd9Sstevel@tonic-gatetimedelta:
7547c478bd9Sstevel@tonic-gate	.word	0, 0		/* int64_t */
7557c478bd9Sstevel@tonic-gatehres_last_tick:
7567c478bd9Sstevel@tonic-gate	.word	0, 0		/* hrtime_t */
7577c478bd9Sstevel@tonic-gatehrestime:
7587c478bd9Sstevel@tonic-gate	.nword	0, 0		/* 2 longs */
7597c478bd9Sstevel@tonic-gatehrestime_adj:
7607c478bd9Sstevel@tonic-gate	.word	0, 0		/* int64_t */
7617c478bd9Sstevel@tonic-gatehres_lock:
7627c478bd9Sstevel@tonic-gate	.word	0
7637c478bd9Sstevel@tonic-gatensec_scale:
7647c478bd9Sstevel@tonic-gate	.word	0
7657c478bd9Sstevel@tonic-gatehrtime_base:
7667c478bd9Sstevel@tonic-gate	.word	0, 0
7677c478bd9Sstevel@tonic-gatetraptrace_use_stick:
7687c478bd9Sstevel@tonic-gate	.word	0
7697c478bd9Sstevel@tonic-gatensec_shift:
7707c478bd9Sstevel@tonic-gate	.word	NSEC_SHIFT
7717c478bd9Sstevel@tonic-gateadj_shift:
7727c478bd9Sstevel@tonic-gate	.word	ADJ_SHIFT
7737c478bd9Sstevel@tonic-gate
7747c478bd9Sstevel@tonic-gate
7757c478bd9Sstevel@tonic-gate/*
7767c478bd9Sstevel@tonic-gate * drv_usecwait(clock_t n)	[DDI/DKI - section 9F]
7777c478bd9Sstevel@tonic-gate * usec_delay(int n)		[compatibility - should go one day]
7787c478bd9Sstevel@tonic-gate * Delay by spinning.
7797c478bd9Sstevel@tonic-gate *
7807c478bd9Sstevel@tonic-gate * delay for n microseconds.  numbers <= 0 delay 1 usec
7817c478bd9Sstevel@tonic-gate *
7827c478bd9Sstevel@tonic-gate * With UltraSPARC-III the combination of supporting mixed-speed CPUs
7837c478bd9Sstevel@tonic-gate * and variable clock rate for power management requires that we
7847c478bd9Sstevel@tonic-gate * use %stick to implement this routine.
78525cf1a30Sjl *
78625cf1a30Sjl * For OPL platforms that support the "sleep" instruction, we
78725cf1a30Sjl * conditionally (ifdef'ed) insert a "sleep" instruction in
78825cf1a30Sjl * the loop. Note that theoritically we should have move (duplicated)
78925cf1a30Sjl * the code down to spitfire/us3/opl specific asm files - but this
79025cf1a30Sjl * is alot of code duplication just to add one "sleep" instruction.
79125cf1a30Sjl * We chose less code duplication for this.
7927c478bd9Sstevel@tonic-gate */
7937c478bd9Sstevel@tonic-gate
7947c478bd9Sstevel@tonic-gate	ENTRY(drv_usecwait)
7957c478bd9Sstevel@tonic-gate	ALTENTRY(usec_delay)
7967c478bd9Sstevel@tonic-gate	brlez,a,pn %o0, 0f
7977c478bd9Sstevel@tonic-gate	mov	1, %o0
7987c478bd9Sstevel@tonic-gate0:
7997c478bd9Sstevel@tonic-gate	sethi	%hi(sticks_per_usec), %o1
8007c478bd9Sstevel@tonic-gate	lduw	[%o1 + %lo(sticks_per_usec)], %o1
8017c478bd9Sstevel@tonic-gate	mulx	%o1, %o0, %o1		! Scale usec to ticks
8027c478bd9Sstevel@tonic-gate	inc	%o1			! We don't start on a tick edge
8037c478bd9Sstevel@tonic-gate	GET_NATIVE_TIME(%o2, %o3, %o4)
8047c478bd9Sstevel@tonic-gate	add	%o1, %o2, %o1
8057c478bd9Sstevel@tonic-gate
80625cf1a30Sjl1:
80725cf1a30Sjl#ifdef	_OPL
80825cf1a30Sjl	.word 0x81b01060		! insert "sleep" instruction
80925cf1a30Sjl#endif /* _OPL */			! use byte code for now
81025cf1a30Sjl	cmp	%o1, %o2
8117c478bd9Sstevel@tonic-gate	GET_NATIVE_TIME(%o2, %o3, %o4)
8127c478bd9Sstevel@tonic-gate	bgeu,pt	%xcc, 1b
8137c478bd9Sstevel@tonic-gate	nop
8147c478bd9Sstevel@tonic-gate	retl
8157c478bd9Sstevel@tonic-gate	nop
8167c478bd9Sstevel@tonic-gate	SET_SIZE(usec_delay)
8177c478bd9Sstevel@tonic-gate	SET_SIZE(drv_usecwait)
8187c478bd9Sstevel@tonic-gate
8197c478bd9Sstevel@tonic-gate/*
8207c478bd9Sstevel@tonic-gate * Level-14 interrupt prologue.
8217c478bd9Sstevel@tonic-gate */
8227c478bd9Sstevel@tonic-gate	ENTRY_NP(pil14_interrupt)
8237c478bd9Sstevel@tonic-gate	CPU_ADDR(%g1, %g2)
8247c478bd9Sstevel@tonic-gate	rdpr	%pil, %g6			! %g6 = interrupted PIL
8257c478bd9Sstevel@tonic-gate	stn	%g6, [%g1 + CPU_PROFILE_PIL]	! record interrupted PIL
8267c478bd9Sstevel@tonic-gate	rdpr	%tstate, %g6
8277c478bd9Sstevel@tonic-gate	rdpr	%tpc, %g5
8287c478bd9Sstevel@tonic-gate	btst	TSTATE_PRIV, %g6		! trap from supervisor mode?
8297c478bd9Sstevel@tonic-gate	bnz,a,pt %xcc, 1f
8307c478bd9Sstevel@tonic-gate	stn	%g5, [%g1 + CPU_PROFILE_PC]	! if so, record kernel PC
8317c478bd9Sstevel@tonic-gate	stn	%g5, [%g1 + CPU_PROFILE_UPC]	! if not, record user PC
8327c478bd9Sstevel@tonic-gate	ba	pil_interrupt_common		! must be large-disp branch
8337c478bd9Sstevel@tonic-gate	stn	%g0, [%g1 + CPU_PROFILE_PC]	! zero kernel PC
8347c478bd9Sstevel@tonic-gate1:	ba	pil_interrupt_common		! must be large-disp branch
8357c478bd9Sstevel@tonic-gate	stn	%g0, [%g1 + CPU_PROFILE_UPC]	! zero user PC
8367c478bd9Sstevel@tonic-gate	SET_SIZE(pil14_interrupt)
8377c478bd9Sstevel@tonic-gate
8387c478bd9Sstevel@tonic-gate	ENTRY_NP(tick_rtt)
8397c478bd9Sstevel@tonic-gate	!
8407c478bd9Sstevel@tonic-gate	! Load TICK_COMPARE into %o5; if bit 63 is set, then TICK_COMPARE is
8417c478bd9Sstevel@tonic-gate	! disabled.  If TICK_COMPARE is enabled, we know that we need to
8427c478bd9Sstevel@tonic-gate	! reenqueue the interrupt request structure.  We'll then check TICKINT
8437c478bd9Sstevel@tonic-gate	! in SOFTINT; if it's set, then we know that we were in a TICK_COMPARE
8447c478bd9Sstevel@tonic-gate	! interrupt.  In this case, TICK_COMPARE may have been rewritten
8457c478bd9Sstevel@tonic-gate	! recently; we'll compare %o5 to the current time to verify that it's
846*5d9d9091SRichard Lowe	! in the future.
8477c478bd9Sstevel@tonic-gate	!
8487c478bd9Sstevel@tonic-gate	! Note that %o5 is live until after 1f.
8497c478bd9Sstevel@tonic-gate	! XXX - there is a subroutine call while %o5 is live!
8507c478bd9Sstevel@tonic-gate	!
8517c478bd9Sstevel@tonic-gate	RD_TICKCMPR(%o5, %g1)
8527c478bd9Sstevel@tonic-gate	srlx	%o5, TICKINT_DIS_SHFT, %g1
8537c478bd9Sstevel@tonic-gate	brnz,pt	%g1, 2f
8547c478bd9Sstevel@tonic-gate	nop
8557c478bd9Sstevel@tonic-gate
8567c478bd9Sstevel@tonic-gate	rdpr 	%pstate, %g5
8577c478bd9Sstevel@tonic-gate	andn	%g5, PSTATE_IE, %g1
8587c478bd9Sstevel@tonic-gate	wrpr	%g0, %g1, %pstate		! Disable vec interrupts
8597c478bd9Sstevel@tonic-gate
8607c478bd9Sstevel@tonic-gate	sethi	%hi(cbe_level14_inum), %o1
861b0fc0e77Sgovinda	ldx	[%o1 + %lo(cbe_level14_inum)], %o1
8627c478bd9Sstevel@tonic-gate	call	intr_enqueue_req ! preserves %o5 and %g5
8637c478bd9Sstevel@tonic-gate	mov	PIL_14, %o0
8647c478bd9Sstevel@tonic-gate
8657c478bd9Sstevel@tonic-gate	! Check SOFTINT for TICKINT/STICKINT
8667c478bd9Sstevel@tonic-gate	rd	SOFTINT, %o4
8677c478bd9Sstevel@tonic-gate	set	(TICK_INT_MASK | STICK_INT_MASK), %o0
8687c478bd9Sstevel@tonic-gate	andcc	%o4, %o0, %g0
8697c478bd9Sstevel@tonic-gate	bz,a,pn	%icc, 2f
8707c478bd9Sstevel@tonic-gate	wrpr	%g0, %g5, %pstate		! Enable vec interrupts
8717c478bd9Sstevel@tonic-gate
8727c478bd9Sstevel@tonic-gate	! clear TICKINT/STICKINT
8737c478bd9Sstevel@tonic-gate	wr	%o0, CLEAR_SOFTINT
8747c478bd9Sstevel@tonic-gate
8757c478bd9Sstevel@tonic-gate	!
8767c478bd9Sstevel@tonic-gate	! Now that we've cleared TICKINT, we can reread %tick and confirm
8777c478bd9Sstevel@tonic-gate	! that the value we programmed is still in the future.  If it isn't,
8787c478bd9Sstevel@tonic-gate	! we need to reprogram TICK_COMPARE to fire as soon as possible.
8797c478bd9Sstevel@tonic-gate	!
8807c478bd9Sstevel@tonic-gate	GET_NATIVE_TIME(%o0, %g1, %g2)		! %o0 = tick
8817c478bd9Sstevel@tonic-gate	sllx	%o0, 1, %o0			! Clear the DIS bit
8827c478bd9Sstevel@tonic-gate	srlx	%o0, 1, %o0
8837c478bd9Sstevel@tonic-gate	cmp	%o5, %o0			! In the future?
8847c478bd9Sstevel@tonic-gate	bg,a,pt	%xcc, 2f			! Yes, drive on.
8857c478bd9Sstevel@tonic-gate	wrpr	%g0, %g5, %pstate		!   delay: enable vec intr
8867c478bd9Sstevel@tonic-gate
8877c478bd9Sstevel@tonic-gate	!
8887c478bd9Sstevel@tonic-gate	! If we're here, then we have programmed TICK_COMPARE with a %tick
8897c478bd9Sstevel@tonic-gate	! which is in the past; we'll now load an initial step size, and loop
8907c478bd9Sstevel@tonic-gate	! until we've managed to program TICK_COMPARE to fire in the future.
8917c478bd9Sstevel@tonic-gate	!
8927c478bd9Sstevel@tonic-gate	mov	8, %o4				! 8 = arbitrary inital step
8937c478bd9Sstevel@tonic-gate1:	add	%o0, %o4, %o5			! Add the step
8947c478bd9Sstevel@tonic-gate	WR_TICKCMPR(%o5,%g1,%g2,__LINE__)	! Write to TICK_CMPR
8957c478bd9Sstevel@tonic-gate	GET_NATIVE_TIME(%o0, %g1, %g2)		! %o0 = tick
8967c478bd9Sstevel@tonic-gate	sllx	%o0, 1, %o0			! Clear the DIS bit
8977c478bd9Sstevel@tonic-gate	srlx	%o0, 1, %o0
8987c478bd9Sstevel@tonic-gate	cmp	%o5, %o0			! In the future?
8997c478bd9Sstevel@tonic-gate	bg,a,pt	%xcc, 2f			! Yes, drive on.
9007c478bd9Sstevel@tonic-gate	wrpr	%g0, %g5, %pstate		!    delay: enable vec intr
9017c478bd9Sstevel@tonic-gate	ba	1b				! No, try again.
9027c478bd9Sstevel@tonic-gate	sllx	%o4, 1, %o4			!    delay: double step size
9037c478bd9Sstevel@tonic-gate
9047c478bd9Sstevel@tonic-gate2:	ba	current_thread_complete
9057c478bd9Sstevel@tonic-gate	nop
9067c478bd9Sstevel@tonic-gate	SET_SIZE(tick_rtt)
9077c478bd9Sstevel@tonic-gate
908b9e93c10SJonathan Haslam/*
909b9e93c10SJonathan Haslam * Level-15 interrupt prologue.
910b9e93c10SJonathan Haslam */
911b9e93c10SJonathan Haslam       ENTRY_NP(pil15_interrupt)
912b9e93c10SJonathan Haslam       CPU_ADDR(%g1, %g2)
913b9e93c10SJonathan Haslam       rdpr    %tstate, %g6
914b9e93c10SJonathan Haslam       rdpr    %tpc, %g5
915b9e93c10SJonathan Haslam       btst    TSTATE_PRIV, %g6                ! trap from supervisor mode?
916b9e93c10SJonathan Haslam       bnz,a,pt %xcc, 1f
917b9e93c10SJonathan Haslam       stn     %g5, [%g1 + CPU_CPCPROFILE_PC]  ! if so, record kernel PC
918b9e93c10SJonathan Haslam       stn     %g5, [%g1 + CPU_CPCPROFILE_UPC] ! if not, record user PC
919b9e93c10SJonathan Haslam       ba      pil15_epilogue                  ! must be large-disp branch
920b9e93c10SJonathan Haslam       stn     %g0, [%g1 + CPU_CPCPROFILE_PC]  ! zero kernel PC
921b9e93c10SJonathan Haslam1:     ba      pil15_epilogue                  ! must be large-disp branch
922b9e93c10SJonathan Haslam       stn     %g0, [%g1 + CPU_CPCPROFILE_UPC] ! zero user PC
923b9e93c10SJonathan Haslam       SET_SIZE(pil15_interrupt)
924b9e93c10SJonathan Haslam
9257c478bd9Sstevel@tonic-gate#ifdef DEBUG
9267c478bd9Sstevel@tonic-gate	.seg	".text"
9277c478bd9Sstevel@tonic-gatefind_cpufreq_panic:
9287c478bd9Sstevel@tonic-gate	.asciz	"find_cpufrequency: interrupts already disabled on entry"
9297c478bd9Sstevel@tonic-gate#endif	/* DEBUG */
9307c478bd9Sstevel@tonic-gate
9317c478bd9Sstevel@tonic-gate	ENTRY_NP(find_cpufrequency)
9327c478bd9Sstevel@tonic-gate	rdpr	%pstate, %g1
9337c478bd9Sstevel@tonic-gate
9347c478bd9Sstevel@tonic-gate#ifdef DEBUG
9357c478bd9Sstevel@tonic-gate	andcc	%g1, PSTATE_IE, %g0	! If DEBUG, check that interrupts
9367c478bd9Sstevel@tonic-gate	bnz	0f			! are currently enabled
9377c478bd9Sstevel@tonic-gate	sethi	%hi(find_cpufreq_panic), %o1
9387c478bd9Sstevel@tonic-gate	call	panic
9397c478bd9Sstevel@tonic-gate	or	%o1, %lo(find_cpufreq_panic), %o0
9407c478bd9Sstevel@tonic-gate#endif	/* DEBUG */
9417c478bd9Sstevel@tonic-gate
9427c478bd9Sstevel@tonic-gate0:
9437c478bd9Sstevel@tonic-gate	wrpr	%g1, PSTATE_IE, %pstate	! Disable interrupts
9447c478bd9Sstevel@tonic-gate3:
9457c478bd9Sstevel@tonic-gate	ldub	[%o0], %o1		! Read the number of seconds
9467c478bd9Sstevel@tonic-gate	mov	%o1, %o2		! remember initial value in %o2
9477c478bd9Sstevel@tonic-gate1:
9487c478bd9Sstevel@tonic-gate	GET_NATIVE_TIME(%o3, %g4, %g5)
9497c478bd9Sstevel@tonic-gate	cmp	%o1, %o2		! did the seconds register roll over?
9507c478bd9Sstevel@tonic-gate	be,pt	%icc, 1b		! branch back if unchanged
9517c478bd9Sstevel@tonic-gate	ldub	[%o0], %o2		!   delay: load the new seconds val
9527c478bd9Sstevel@tonic-gate
9537c478bd9Sstevel@tonic-gate	brz,pn	%o2, 3b			! if the minutes just rolled over,
9547c478bd9Sstevel@tonic-gate					! the last second could have been
9557c478bd9Sstevel@tonic-gate					! inaccurate; try again.
9567c478bd9Sstevel@tonic-gate	mov	%o2, %o4		!   delay: store init. val. in %o2
9577c478bd9Sstevel@tonic-gate2:
9587c478bd9Sstevel@tonic-gate	GET_NATIVE_TIME(%o5, %g4, %g5)
9597c478bd9Sstevel@tonic-gate	cmp	%o2, %o4		! did the seconds register roll over?
9607c478bd9Sstevel@tonic-gate	be,pt	%icc, 2b		! branch back if unchanged
9617c478bd9Sstevel@tonic-gate	ldub	[%o0], %o4		!   delay: load the new seconds val
9627c478bd9Sstevel@tonic-gate
9637c478bd9Sstevel@tonic-gate	brz,pn	%o4, 0b			! if the minutes just rolled over,
9647c478bd9Sstevel@tonic-gate					! the last second could have been
9657c478bd9Sstevel@tonic-gate					! inaccurate; try again.
9667c478bd9Sstevel@tonic-gate	wrpr	%g0, %g1, %pstate	!   delay: re-enable interrupts
9677c478bd9Sstevel@tonic-gate
9687c478bd9Sstevel@tonic-gate	retl
9697c478bd9Sstevel@tonic-gate	sub	%o5, %o3, %o0		! return the difference in ticks
9707c478bd9Sstevel@tonic-gate	SET_SIZE(find_cpufrequency)
9717c478bd9Sstevel@tonic-gate
9727c478bd9Sstevel@tonic-gate#if defined(CHEETAH) || defined(CHEETAH_PLUS) || defined(JALAPENO) || \
9737c478bd9Sstevel@tonic-gate	defined(SERRANO)
9747c478bd9Sstevel@tonic-gate	!
9757c478bd9Sstevel@tonic-gate	! On US-III, the prefetch instruction queue is 8 entries deep.
9767c478bd9Sstevel@tonic-gate	! Also, prefetches for write put data in the E$, which has
9777c478bd9Sstevel@tonic-gate	! lines of 512 bytes for an 8MB cache. Each E$ line is further
9787c478bd9Sstevel@tonic-gate	! subblocked into 64 byte chunks.
9797c478bd9Sstevel@tonic-gate	!
9807c478bd9Sstevel@tonic-gate	! Since prefetch can only bring in 64 bytes at a time (See Sparc
9817c478bd9Sstevel@tonic-gate	! v9 Architecture Manual pp.204) and a page_t is 128 bytes,
9827c478bd9Sstevel@tonic-gate	! then 2 prefetches are required in order to bring an entire
9837c478bd9Sstevel@tonic-gate	! page into the E$.
9847c478bd9Sstevel@tonic-gate	!
9857c478bd9Sstevel@tonic-gate	! Since the prefetch queue is 8 entries deep, we currently can
9867c478bd9Sstevel@tonic-gate	! only have 4 prefetches for page_t's outstanding. Thus, we
987*5d9d9091SRichard Lowe	! prefetch n+4 ahead of where we are now:
9887c478bd9Sstevel@tonic-gate	!
9897c478bd9Sstevel@tonic-gate	!      4 * sizeof(page_t)     -> 512
9907c478bd9Sstevel@tonic-gate	!      4 * sizeof(page_t) +64 -> 576
991*5d9d9091SRichard Lowe	!
9927c478bd9Sstevel@tonic-gate	! Example
9937c478bd9Sstevel@tonic-gate	! =======
9947c478bd9Sstevel@tonic-gate	! contiguous page array in memory...
9957c478bd9Sstevel@tonic-gate	!
9967c478bd9Sstevel@tonic-gate	! |AAA1|AAA2|BBB1|BBB2|CCC1|CCC2|DDD1|DDD2|XXX1|XXX2|YYY1|YYY2|...
9977c478bd9Sstevel@tonic-gate	! ^         ^         ^         ^         ^    ^
9987c478bd9Sstevel@tonic-gate	! pp                                      |    pp+4*sizeof(page)+64
9997c478bd9Sstevel@tonic-gate	!                                         |
10007c478bd9Sstevel@tonic-gate	!                                         pp+4*sizeof(page)
10017c478bd9Sstevel@tonic-gate	!
10027c478bd9Sstevel@tonic-gate	!  Prefetch
10037c478bd9Sstevel@tonic-gate	!   Queue
10047c478bd9Sstevel@tonic-gate	! +-------+<--- In this iteration, we're working with pp (AAA1),
10057c478bd9Sstevel@tonic-gate	! |Preftch|     but we enqueue prefetch for addr = XXX1
1006*5d9d9091SRichard Lowe	! | XXX1  |
10077c478bd9Sstevel@tonic-gate	! +-------+<--- this queue slot will be a prefetch instruction for
10087c478bd9Sstevel@tonic-gate	! |Preftch|     for addr = pp + 4*sizeof(page_t) + 64 (or second
10097c478bd9Sstevel@tonic-gate	! | XXX2  |     half of page XXX)
1010*5d9d9091SRichard Lowe	! +-------+
10117c478bd9Sstevel@tonic-gate	! |Preftch|<-+- The next time around this function, we'll be
10127c478bd9Sstevel@tonic-gate	! | YYY1  |  |  working with pp = BBB1, but will be enqueueing
10137c478bd9Sstevel@tonic-gate	! +-------+  |  prefetches to for both halves of page YYY,
10147c478bd9Sstevel@tonic-gate	! |Preftch|  |  while both halves of page XXX are in transit
10157c478bd9Sstevel@tonic-gate	! | YYY2  |<-+  make their way into the E$.
10167c478bd9Sstevel@tonic-gate	! +-------+
10177c478bd9Sstevel@tonic-gate	! |Preftch|
10187c478bd9Sstevel@tonic-gate	! | ZZZ1  |
10197c478bd9Sstevel@tonic-gate	! +-------+
10207c478bd9Sstevel@tonic-gate	! .       .
10217c478bd9Sstevel@tonic-gate	! :       :
10227c478bd9Sstevel@tonic-gate	!
10237c478bd9Sstevel@tonic-gate	!  E$
10247c478bd9Sstevel@tonic-gate	! +============================================...
10257c478bd9Sstevel@tonic-gate	! | XXX1 | XXX2 | YYY1 | YYY2 | ZZZ1 | ZZZ2 |
10267c478bd9Sstevel@tonic-gate	! +============================================...
10277c478bd9Sstevel@tonic-gate	! |      |      |      |      |      |      |
10287c478bd9Sstevel@tonic-gate	! +============================================...
10297c478bd9Sstevel@tonic-gate	! .
10307c478bd9Sstevel@tonic-gate	! :
10317c478bd9Sstevel@tonic-gate	!
10327c478bd9Sstevel@tonic-gate	! So we should expect the first four page accesses to stall
10337c478bd9Sstevel@tonic-gate	! while we warm up the cache, afterwhich, most of the pages
10347c478bd9Sstevel@tonic-gate	! will have their pp ready in the E$.
1035*5d9d9091SRichard Lowe	!
1036*5d9d9091SRichard Lowe	! Also note that if sizeof(page_t) grows beyond 128, then
10377c478bd9Sstevel@tonic-gate	! we'll need an additional prefetch to get an entire page
10387c478bd9Sstevel@tonic-gate	! into the E$, thus reducing the number of outstanding page
10397c478bd9Sstevel@tonic-gate	! prefetches to 2 (ie. 3 prefetches/page = 6 queue slots)
10407c478bd9Sstevel@tonic-gate	! etc.
10417c478bd9Sstevel@tonic-gate	!
10427c478bd9Sstevel@tonic-gate	! Cheetah+
10437c478bd9Sstevel@tonic-gate	! ========
10447c478bd9Sstevel@tonic-gate	! On Cheetah+ we use "#n_write" prefetches as these avoid
10457c478bd9Sstevel@tonic-gate	! unnecessary RTS->RTO bus transaction state change, and
10467c478bd9Sstevel@tonic-gate	! just issues RTO transaction. (See pp.77 of Cheetah+ Delta
10477c478bd9Sstevel@tonic-gate	! PRM). On Cheetah, #n_write prefetches are reflected with
10487c478bd9Sstevel@tonic-gate	! RTS->RTO state transition regardless.
10497c478bd9Sstevel@tonic-gate	!
10507c478bd9Sstevel@tonic-gate#define STRIDE1 512
10517c478bd9Sstevel@tonic-gate#define STRIDE2 576
10527c478bd9Sstevel@tonic-gate
10537c478bd9Sstevel@tonic-gate#if	STRIDE1 != (PAGE_SIZE * 4)
10547c478bd9Sstevel@tonic-gate#error	"STRIDE1 != (PAGE_SIZE * 4)"
10557c478bd9Sstevel@tonic-gate#endif	/* STRIDE1 != (PAGE_SIZE * 4) */
10567c478bd9Sstevel@tonic-gate
10579b0bb795SJohn Levon/*
10589b0bb795SJohn Levon * Prefetch a page_t for write or read, this assumes a linear
10599b0bb795SJohn Levon * scan of sequential page_t's.
10609b0bb795SJohn Levon */
10617c478bd9Sstevel@tonic-gate        ENTRY(prefetch_page_w)
10627c478bd9Sstevel@tonic-gate        prefetch        [%o0+STRIDE1], #n_writes
10637c478bd9Sstevel@tonic-gate        retl
10647c478bd9Sstevel@tonic-gate        prefetch        [%o0+STRIDE2], #n_writes
10657c478bd9Sstevel@tonic-gate        SET_SIZE(prefetch_page_w)
10667c478bd9Sstevel@tonic-gate
10677c478bd9Sstevel@tonic-gate	!
10687c478bd9Sstevel@tonic-gate	! Note on CHEETAH to prefetch for read, we really use #one_write.
10697c478bd9Sstevel@tonic-gate	! This fetches to E$ (general use) rather than P$ (floating point use).
10707c478bd9Sstevel@tonic-gate	!
10717c478bd9Sstevel@tonic-gate        ENTRY(prefetch_page_r)
10727c478bd9Sstevel@tonic-gate        prefetch        [%o0+STRIDE1], #one_write
10737c478bd9Sstevel@tonic-gate        retl
10747c478bd9Sstevel@tonic-gate        prefetch        [%o0+STRIDE2], #one_write
10757c478bd9Sstevel@tonic-gate        SET_SIZE(prefetch_page_r)
10767c478bd9Sstevel@tonic-gate
10777c478bd9Sstevel@tonic-gate#elif defined(SPITFIRE) || defined(HUMMINGBIRD)
10787c478bd9Sstevel@tonic-gate
10797c478bd9Sstevel@tonic-gate	!
10807c478bd9Sstevel@tonic-gate	! UltraSparcII can have up to 3 prefetches outstanding.
10817c478bd9Sstevel@tonic-gate	! A page_t is 128 bytes (2 prefetches of 64 bytes each)
10827c478bd9Sstevel@tonic-gate	! So prefetch for pp + 1, which is
10837c478bd9Sstevel@tonic-gate	!
10847c478bd9Sstevel@tonic-gate	!       pp + sizeof(page_t)
10857c478bd9Sstevel@tonic-gate	! and
10867c478bd9Sstevel@tonic-gate	!       pp + sizeof(page_t) + 64
10877c478bd9Sstevel@tonic-gate	!
10887c478bd9Sstevel@tonic-gate#define STRIDE1	128
10897c478bd9Sstevel@tonic-gate#define STRIDE2	192
10907c478bd9Sstevel@tonic-gate
10917c478bd9Sstevel@tonic-gate#if	STRIDE1 != PAGE_SIZE
10927c478bd9Sstevel@tonic-gate#error	"STRIDE1 != PAGE_SIZE"
10937c478bd9Sstevel@tonic-gate#endif	/* STRIDE1 != PAGE_SIZE */
10947c478bd9Sstevel@tonic-gate
10957c478bd9Sstevel@tonic-gate        ENTRY(prefetch_page_w)
10967c478bd9Sstevel@tonic-gate        prefetch        [%o0+STRIDE1], #n_writes
10977c478bd9Sstevel@tonic-gate        retl
10987c478bd9Sstevel@tonic-gate        prefetch        [%o0+STRIDE2], #n_writes
10997c478bd9Sstevel@tonic-gate        SET_SIZE(prefetch_page_w)
11007c478bd9Sstevel@tonic-gate
11017c478bd9Sstevel@tonic-gate        ENTRY(prefetch_page_r)
11027c478bd9Sstevel@tonic-gate        prefetch        [%o0+STRIDE1], #n_reads
11037c478bd9Sstevel@tonic-gate        retl
11047c478bd9Sstevel@tonic-gate        prefetch        [%o0+STRIDE2], #n_reads
11057c478bd9Sstevel@tonic-gate        SET_SIZE(prefetch_page_r)
110625cf1a30Sjl
110725cf1a30Sjl#elif defined(OLYMPUS_C)
110825cf1a30Sjl	!
1109e4896ad2Shyw	! Prefetch strides for Olympus-C
111025cf1a30Sjl	!
111125cf1a30Sjl
1112e4896ad2Shyw#define STRIDE1	0x440
1113e4896ad2Shyw#define STRIDE2	0x640
1114*5d9d9091SRichard Lowe
111525cf1a30Sjl	ENTRY(prefetch_page_w)
111625cf1a30Sjl        prefetch        [%o0+STRIDE1], #n_writes
111725cf1a30Sjl	retl
111825cf1a30Sjl        prefetch        [%o0+STRIDE2], #n_writes
111925cf1a30Sjl	SET_SIZE(prefetch_page_w)
112025cf1a30Sjl
112125cf1a30Sjl	ENTRY(prefetch_page_r)
112225cf1a30Sjl        prefetch        [%o0+STRIDE1], #n_writes
112325cf1a30Sjl	retl
112425cf1a30Sjl        prefetch        [%o0+STRIDE2], #n_writes
112525cf1a30Sjl	SET_SIZE(prefetch_page_r)
112625cf1a30Sjl#else	/* OLYMPUS_C */
11277c478bd9Sstevel@tonic-gate
11287c478bd9Sstevel@tonic-gate#error "You need to fix this for your new cpu type."
11297c478bd9Sstevel@tonic-gate
113025cf1a30Sjl#endif	/* OLYMPUS_C */
11317c478bd9Sstevel@tonic-gate
11327c478bd9Sstevel@tonic-gate#if defined(CHEETAH) || defined(CHEETAH_PLUS) || defined(JALAPENO) || \
11337c478bd9Sstevel@tonic-gate	defined(SERRANO)
11347c478bd9Sstevel@tonic-gate
11357c478bd9Sstevel@tonic-gate#define	PREFETCH_Q_LEN 8
11367c478bd9Sstevel@tonic-gate
11377c478bd9Sstevel@tonic-gate#elif defined(SPITFIRE) || defined(HUMMINGBIRD)
11387c478bd9Sstevel@tonic-gate
11397c478bd9Sstevel@tonic-gate#define	PREFETCH_Q_LEN 3
11407c478bd9Sstevel@tonic-gate
114125cf1a30Sjl#elif defined(OLYMPUS_C)
114225cf1a30Sjl	!
1143e4896ad2Shyw	! Use length of one for now.
1144e4896ad2Shyw	!
114525cf1a30Sjl#define	PREFETCH_Q_LEN	1
114625cf1a30Sjl
114725cf1a30Sjl#else 	/* OLYMPUS_C */
11487c478bd9Sstevel@tonic-gate
11497c478bd9Sstevel@tonic-gate#error You need to fix this for your new cpu type.
11507c478bd9Sstevel@tonic-gate
115125cf1a30Sjl#endif	/* OLYMPUS_C */
11527c478bd9Sstevel@tonic-gate
11537c478bd9Sstevel@tonic-gate#include <vm/kpm.h>
11547c478bd9Sstevel@tonic-gate
11557c478bd9Sstevel@tonic-gate#ifdef	SEGKPM_SUPPORT
11567c478bd9Sstevel@tonic-gate
11577c478bd9Sstevel@tonic-gate#define	SMAP_SIZE 72
11587c478bd9Sstevel@tonic-gate#define SMAP_STRIDE (((PREFETCH_Q_LEN * 64) / SMAP_SIZE) * 64)
11597c478bd9Sstevel@tonic-gate
11607c478bd9Sstevel@tonic-gate#else	/* SEGKPM_SUPPORT */
11617c478bd9Sstevel@tonic-gate
11627c478bd9Sstevel@tonic-gate	!
11637c478bd9Sstevel@tonic-gate	! The hardware will prefetch the 64 byte cache aligned block
11647c478bd9Sstevel@tonic-gate	! that contains the address specified in the prefetch instruction.
11657c478bd9Sstevel@tonic-gate	! Since the size of the smap struct is 48 bytes, issuing 1 prefetch
11667c478bd9Sstevel@tonic-gate	! per pass will suffice as long as we prefetch far enough ahead to
11677c478bd9Sstevel@tonic-gate	! make sure we don't stall for the cases where the smap object
11687c478bd9Sstevel@tonic-gate	! spans multiple hardware prefetch blocks.  Let's prefetch as far
11697c478bd9Sstevel@tonic-gate	! ahead as the hardware will allow.
11707c478bd9Sstevel@tonic-gate	!
11717c478bd9Sstevel@tonic-gate	! The smap array is processed with decreasing address pointers.
11727c478bd9Sstevel@tonic-gate	!
11737c478bd9Sstevel@tonic-gate#define	SMAP_SIZE 48
11747c478bd9Sstevel@tonic-gate#define	SMAP_STRIDE (PREFETCH_Q_LEN * SMAP_SIZE)
11757c478bd9Sstevel@tonic-gate
11767c478bd9Sstevel@tonic-gate#endif	/* SEGKPM_SUPPORT */
11777c478bd9Sstevel@tonic-gate
11789b0bb795SJohn Levon/*
11799b0bb795SJohn Levon * Prefetch struct smap for write.
11809b0bb795SJohn Levon */
11817c478bd9Sstevel@tonic-gate	ENTRY(prefetch_smap_w)
11827c478bd9Sstevel@tonic-gate	retl
11837c478bd9Sstevel@tonic-gate	prefetch	[%o0-SMAP_STRIDE], #n_writes
11847c478bd9Sstevel@tonic-gate	SET_SIZE(prefetch_smap_w)
11857c478bd9Sstevel@tonic-gate
11867c478bd9Sstevel@tonic-gate	ENTRY_NP(getidsr)
11877c478bd9Sstevel@tonic-gate	retl
11887c478bd9Sstevel@tonic-gate	ldxa	[%g0]ASI_INTR_DISPATCH_STATUS, %o0
11897c478bd9Sstevel@tonic-gate	SET_SIZE(getidsr)
1190