xref: /onnv-gate/usr/src/uts/sun4u/sys/machclock.h (revision 12235:a4f889396df4)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51772Sjl139090  * Common Development and Distribution License (the "License").
61772Sjl139090  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*12235Sprashanth.sreenivasa@oracle.com  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate  */
240Sstevel@tonic-gate 
250Sstevel@tonic-gate #ifndef _SYS_MACHCLOCK_H
260Sstevel@tonic-gate #define	_SYS_MACHCLOCK_H
270Sstevel@tonic-gate 
280Sstevel@tonic-gate #ifdef	__cplusplus
290Sstevel@tonic-gate extern "C" {
300Sstevel@tonic-gate #endif
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #ifdef _ASM
330Sstevel@tonic-gate /*
340Sstevel@tonic-gate  * Macro to clear the NPT (non-privileged trap) bit in the %tick/%stick
350Sstevel@tonic-gate  * register.  Uses %g1-%g4.
360Sstevel@tonic-gate  */
370Sstevel@tonic-gate #define	CLEARTICKNPT				\
380Sstevel@tonic-gate 	sethi	%hi(cpu_clearticknpt), %g1;	\
390Sstevel@tonic-gate 	jmp	%g1 + %lo(cpu_clearticknpt);	\
400Sstevel@tonic-gate 	rd	%pc, %g4
410Sstevel@tonic-gate 
4211172SHaik.Aftandilian@Sun.COM #define	RD_TICK_NO_SUSPEND_CHECK(out, scr1)	\
4311172SHaik.Aftandilian@Sun.COM 	rdpr	%tick, out;			\
4411172SHaik.Aftandilian@Sun.COM 	sllx	out, 1, out;			\
4511172SHaik.Aftandilian@Sun.COM 	srlx	out, 1, out;
4611172SHaik.Aftandilian@Sun.COM 
4711172SHaik.Aftandilian@Sun.COM #define	RD_TICK(out, scr1, scr2, label)		\
4811172SHaik.Aftandilian@Sun.COM 	RD_TICK_NO_SUSPEND_CHECK(out, scr1);
4911172SHaik.Aftandilian@Sun.COM 
50*12235Sprashanth.sreenivasa@oracle.com /*
51*12235Sprashanth.sreenivasa@oracle.com  * These macros on sun4u read the %tick register, due to :
52*12235Sprashanth.sreenivasa@oracle.com  * - %stick does not have enough precision, it's very low frequency
53*12235Sprashanth.sreenivasa@oracle.com  * - %stick accesses are very slow on UltraSPARC IIe
54*12235Sprashanth.sreenivasa@oracle.com  * Instead, consumers read %tick and scale it by the current stick/tick ratio.
55*12235Sprashanth.sreenivasa@oracle.com  * This only works because all cpus in a system change clock ratios
56*12235Sprashanth.sreenivasa@oracle.com  * synchronously and the changes are all initiated by the kernel.
57*12235Sprashanth.sreenivasa@oracle.com  */
58*12235Sprashanth.sreenivasa@oracle.com #define	RD_CLOCK_TICK(out, scr1, scr2, label)	\
59*12235Sprashanth.sreenivasa@oracle.com /* CSTYLED */					\
60*12235Sprashanth.sreenivasa@oracle.com 	RD_TICK(out,scr1,scr2,label)
61*12235Sprashanth.sreenivasa@oracle.com 
62*12235Sprashanth.sreenivasa@oracle.com #define	RD_CLOCK_TICK_NO_SUSPEND_CHECK(out, scr1)	\
63*12235Sprashanth.sreenivasa@oracle.com /* CSTYLED */						\
64*12235Sprashanth.sreenivasa@oracle.com 	RD_TICK_NO_SUSPEND_CHECK(out,scr1)
65*12235Sprashanth.sreenivasa@oracle.com 
660Sstevel@tonic-gate #endif /* _ASM */
670Sstevel@tonic-gate 
680Sstevel@tonic-gate #if defined(CPU_MODULE)
690Sstevel@tonic-gate 
700Sstevel@tonic-gate /*
710Sstevel@tonic-gate  * Constants used to convert hi-res timestamps into nanoseconds
720Sstevel@tonic-gate  * (see <sys/clock.h> file for more information)
730Sstevel@tonic-gate  */
740Sstevel@tonic-gate 
751772Sjl139090 #if defined(CHEETAH) || defined(HUMMINGBIRD) || defined(OLYMPUS_C)
760Sstevel@tonic-gate 
770Sstevel@tonic-gate /*
780Sstevel@tonic-gate  * At least 3.9MHz, for slower %stick-based systems.
790Sstevel@tonic-gate  */
800Sstevel@tonic-gate #define	NSEC_SHIFT	8
810Sstevel@tonic-gate 
820Sstevel@tonic-gate #elif defined(SPITFIRE)
830Sstevel@tonic-gate 
840Sstevel@tonic-gate /*
850Sstevel@tonic-gate  * At least 62.5 MHz, for faster %tick-based systems.
860Sstevel@tonic-gate  */
870Sstevel@tonic-gate #define	NSEC_SHIFT	4
880Sstevel@tonic-gate #define	VTRACE_SHIFT	4
890Sstevel@tonic-gate 
900Sstevel@tonic-gate #else
910Sstevel@tonic-gate #error "Compiling for CPU_MODULE but no CPU specified"
920Sstevel@tonic-gate #endif
930Sstevel@tonic-gate 
9411172SHaik.Aftandilian@Sun.COM /*
9511172SHaik.Aftandilian@Sun.COM  * NOTE: the macros below assume that the various time-related variables
9611172SHaik.Aftandilian@Sun.COM  * (hrestime, hrestime_adj, hres_last_tick, timedelta, nsec_scale, etc)
9711172SHaik.Aftandilian@Sun.COM  * are all stored together on a 64-byte boundary.  The primary motivation
9811172SHaik.Aftandilian@Sun.COM  * is cache performance, but we also take advantage of a convenient side
9911172SHaik.Aftandilian@Sun.COM  * effect: these variables all have the same high 22 address bits, so only
10011172SHaik.Aftandilian@Sun.COM  * one sethi is needed to access them all.
10111172SHaik.Aftandilian@Sun.COM  */
10211172SHaik.Aftandilian@Sun.COM 
10311172SHaik.Aftandilian@Sun.COM /*
10411172SHaik.Aftandilian@Sun.COM  * GET_HRESTIME() returns the value of hrestime, hrestime_adj and the
10511172SHaik.Aftandilian@Sun.COM  * number of nanoseconds since the last clock tick ('nslt').  It also
10611172SHaik.Aftandilian@Sun.COM  * sets 'nano' to the value NANOSEC (one billion).
10711172SHaik.Aftandilian@Sun.COM  *
10811172SHaik.Aftandilian@Sun.COM  * This macro assumes that all registers are globals or outs so they can
10911172SHaik.Aftandilian@Sun.COM  * safely contain 64-bit data, and that it's safe to use the label "5:".
11011172SHaik.Aftandilian@Sun.COM  * Further, this macro calls the NATIVE_TIME_TO_NSEC_SCALE which in turn
11111172SHaik.Aftandilian@Sun.COM  * uses the labels "6:" and "7:"; labels "5:", "6:" and "7:" must not
11211172SHaik.Aftandilian@Sun.COM  * be used across invocations of this macro.
11311172SHaik.Aftandilian@Sun.COM  */
11411172SHaik.Aftandilian@Sun.COM #define	GET_HRESTIME(hrestsec, hrestnsec, adj, nslt, nano, scr, hrlock, \
11511172SHaik.Aftandilian@Sun.COM     gnt1, gnt2) \
11611172SHaik.Aftandilian@Sun.COM 5:	sethi	%hi(hres_lock), scr;					\
11711172SHaik.Aftandilian@Sun.COM 	lduw	[scr + %lo(hres_lock)], hrlock;	/* load clock lock */	\
11811172SHaik.Aftandilian@Sun.COM 	lduw	[scr + %lo(nsec_scale)], nano;	/* tick-to-ns factor */	\
11911172SHaik.Aftandilian@Sun.COM 	andn	hrlock, 1, hrlock;  	/* see comments above! */	\
12011172SHaik.Aftandilian@Sun.COM 	ldx	[scr + %lo(hres_last_tick)], nslt;			\
12111172SHaik.Aftandilian@Sun.COM 	ldn	[scr + %lo(hrestime)], hrestsec; /* load hrestime.sec */\
12211172SHaik.Aftandilian@Sun.COM 	add	scr, %lo(hrestime), hrestnsec;				\
12311172SHaik.Aftandilian@Sun.COM 	ldn	[hrestnsec + CLONGSIZE], hrestnsec;			\
12411172SHaik.Aftandilian@Sun.COM 	GET_NATIVE_TIME(adj, gnt1, gnt2);	/* get current %tick */	\
12511172SHaik.Aftandilian@Sun.COM 	subcc	adj, nslt, nslt; /* nslt = ticks since last clockint */	\
12611172SHaik.Aftandilian@Sun.COM 	movneg	%xcc, %g0, nslt; /* ignore neg delta from tick skew */	\
12711172SHaik.Aftandilian@Sun.COM 	ldx	[scr + %lo(hrestime_adj)], adj; /* load hrestime_adj */	\
12811172SHaik.Aftandilian@Sun.COM 	/* membar #LoadLoad; (see comment (2) above) */			\
12911172SHaik.Aftandilian@Sun.COM 	lduw	[scr + %lo(hres_lock)], scr; /* load clock lock */	\
13011172SHaik.Aftandilian@Sun.COM 	NATIVE_TIME_TO_NSEC_SCALE(nslt, nano, gnt1, NSEC_SHIFT);	\
13111172SHaik.Aftandilian@Sun.COM 	sethi	%hi(NANOSEC), nano;					\
13211172SHaik.Aftandilian@Sun.COM 	xor	hrlock, scr, scr;					\
13311172SHaik.Aftandilian@Sun.COM /* CSTYLED */ 								\
13411172SHaik.Aftandilian@Sun.COM 	brnz,pn	scr, 5b;						\
13511172SHaik.Aftandilian@Sun.COM 	or	nano, %lo(NANOSEC), nano;
13611172SHaik.Aftandilian@Sun.COM 
13711172SHaik.Aftandilian@Sun.COM /*
13811172SHaik.Aftandilian@Sun.COM  * Similar to above, but returns current gethrtime() value in 'base'.
13911172SHaik.Aftandilian@Sun.COM  */
14011172SHaik.Aftandilian@Sun.COM #define	GET_HRTIME(base, now, nslt, scale, scr, hrlock, gnt1, gnt2)	\
14111172SHaik.Aftandilian@Sun.COM 5:	sethi	%hi(hres_lock), scr;					\
14211172SHaik.Aftandilian@Sun.COM 	lduw	[scr + %lo(hres_lock)], hrlock;	/* load clock lock */	\
14311172SHaik.Aftandilian@Sun.COM 	lduw	[scr + %lo(nsec_scale)], scale;	/* tick-to-ns factor */	\
14411172SHaik.Aftandilian@Sun.COM 	andn	hrlock, 1, hrlock;  	/* see comments above! */	\
14511172SHaik.Aftandilian@Sun.COM 	ldx	[scr + %lo(hres_last_tick)], nslt;			\
14611172SHaik.Aftandilian@Sun.COM 	ldx	[scr + %lo(hrtime_base)], base;	/* load hrtime_base */	\
14711172SHaik.Aftandilian@Sun.COM 	GET_NATIVE_TIME(now, gnt1, gnt2);	/* get current %tick */	\
14811172SHaik.Aftandilian@Sun.COM 	subcc	now, nslt, nslt; /* nslt = ticks since last clockint */	\
14911172SHaik.Aftandilian@Sun.COM 	movneg	%xcc, %g0, nslt; /* ignore neg delta from tick skew */	\
15011172SHaik.Aftandilian@Sun.COM 	/* membar #LoadLoad; (see comment (2) above) */			\
15111172SHaik.Aftandilian@Sun.COM 	ld	[scr + %lo(hres_lock)], scr; /* load clock lock */	\
15211172SHaik.Aftandilian@Sun.COM 	NATIVE_TIME_TO_NSEC_SCALE(nslt, scale, gnt1, NSEC_SHIFT);	\
15311172SHaik.Aftandilian@Sun.COM 	xor	hrlock, scr, scr;					\
15411172SHaik.Aftandilian@Sun.COM /* CSTYLED */ 								\
15511172SHaik.Aftandilian@Sun.COM 	brnz,pn	scr, 5b;						\
15611172SHaik.Aftandilian@Sun.COM 	add	base, nslt, base;
15711172SHaik.Aftandilian@Sun.COM 
1580Sstevel@tonic-gate #endif /* CPU_MODULE */
1590Sstevel@tonic-gate 
1600Sstevel@tonic-gate #ifndef _ASM
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate #ifdef	_KERNEL
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate /*
1650Sstevel@tonic-gate  * Hardware watchdog variables and knobs
1660Sstevel@tonic-gate  */
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate #define	CLK_WATCHDOG_DEFAULT	10	/* 10 seconds */
1690Sstevel@tonic-gate 
1700Sstevel@tonic-gate extern int	watchdog_enable;
1710Sstevel@tonic-gate extern int	watchdog_available;
1720Sstevel@tonic-gate extern int	watchdog_activated;
1730Sstevel@tonic-gate extern uint_t	watchdog_timeout_seconds;
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate /*
1760Sstevel@tonic-gate  * tod module name and operations
1770Sstevel@tonic-gate  */
1780Sstevel@tonic-gate struct tod_ops {
1790Sstevel@tonic-gate 	timestruc_t	(*tod_get)(void);
1800Sstevel@tonic-gate 	void		(*tod_set)(timestruc_t);
1810Sstevel@tonic-gate 	uint_t		(*tod_set_watchdog_timer)(uint_t);
1820Sstevel@tonic-gate 	uint_t		(*tod_clear_watchdog_timer)(void);
1830Sstevel@tonic-gate 	void		(*tod_set_power_alarm)(timestruc_t);
1840Sstevel@tonic-gate 	void		(*tod_clear_power_alarm)(void);
1850Sstevel@tonic-gate 	uint64_t	(*tod_get_cpufrequency)(void);
1860Sstevel@tonic-gate };
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate extern struct tod_ops	tod_ops;
1890Sstevel@tonic-gate extern char		*tod_module_name;
1900Sstevel@tonic-gate 
191*12235Sprashanth.sreenivasa@oracle.com extern uint64_t gettick_counter(void);
192*12235Sprashanth.sreenivasa@oracle.com #define	CLOCK_TICK_COUNTER() gettick_counter()
193*12235Sprashanth.sreenivasa@oracle.com 
1945295Srandyf /*
1955295Srandyf  * These defines allow common code to use TOD functions independant
1965295Srandyf  * of hardware platform.
1975295Srandyf  */
1985295Srandyf #define	TODOP_GET(top)		((top).tod_get())
1995295Srandyf #define	TODOP_SET(top, ts)	((top).tod_set(ts))
2005295Srandyf #define	TODOP_SETWD(top, nsec)	((top).tod_set_watchdog_timer(nsec))
2015295Srandyf #define	TODOP_CLRWD(top)	((top).tod_clear_watchdog_timer())
2025295Srandyf #define	TODOP_SETWAKE(top, ts)	((top).tod_set_power_alarm(ts))
2035295Srandyf #define	TODOP_CLRWAKE(top)	((top).tod_clear_power_alarm())
2045295Srandyf 
2050Sstevel@tonic-gate #endif	/* _KERNEL */
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate #endif	/* _ASM */
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate #ifdef	__cplusplus
2100Sstevel@tonic-gate }
2110Sstevel@tonic-gate #endif
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate #endif	/* !_SYS_MACHCLOCK_H */
214