xref: /illumos-gate/usr/src/uts/sun4u/sys/machclock.h (revision bd28a477)
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 /*
22*bd28a477SPrashanth Sreenivasa  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate #ifndef _SYS_MACHCLOCK_H
267c478bd9Sstevel@tonic-gate #define	_SYS_MACHCLOCK_H
287c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
297c478bd9Sstevel@tonic-gate extern "C" {
307c478bd9Sstevel@tonic-gate #endif
327c478bd9Sstevel@tonic-gate #ifdef _ASM
337c478bd9Sstevel@tonic-gate /*
347c478bd9Sstevel@tonic-gate  * Macro to clear the NPT (non-privileged trap) bit in the %tick/%stick
357c478bd9Sstevel@tonic-gate  * register.  Uses %g1-%g4.
367c478bd9Sstevel@tonic-gate  */
377c478bd9Sstevel@tonic-gate #define	CLEARTICKNPT				\
387c478bd9Sstevel@tonic-gate 	sethi	%hi(cpu_clearticknpt), %g1;	\
397c478bd9Sstevel@tonic-gate 	jmp	%g1 + %lo(cpu_clearticknpt);	\
407c478bd9Sstevel@tonic-gate 	rd	%pc, %g4
42023e71deSHaik Aftandilian #define	RD_TICK_NO_SUSPEND_CHECK(out, scr1)	\
43023e71deSHaik Aftandilian 	rdpr	%tick, out;			\
44023e71deSHaik Aftandilian 	sllx	out, 1, out;			\
45023e71deSHaik Aftandilian 	srlx	out, 1, out;
46023e71deSHaik Aftandilian 
47023e71deSHaik Aftandilian #define	RD_TICK(out, scr1, scr2, label)		\
48023e71deSHaik Aftandilian 	RD_TICK_NO_SUSPEND_CHECK(out, scr1);
49023e71deSHaik Aftandilian 
50*bd28a477SPrashanth Sreenivasa /*
51*bd28a477SPrashanth Sreenivasa  * These macros on sun4u read the %tick register, due to :
52*bd28a477SPrashanth Sreenivasa  * - %stick does not have enough precision, it's very low frequency
53*bd28a477SPrashanth Sreenivasa  * - %stick accesses are very slow on UltraSPARC IIe
54*bd28a477SPrashanth Sreenivasa  * Instead, consumers read %tick and scale it by the current stick/tick ratio.
55*bd28a477SPrashanth Sreenivasa  * This only works because all cpus in a system change clock ratios
56*bd28a477SPrashanth Sreenivasa  * synchronously and the changes are all initiated by the kernel.
57*bd28a477SPrashanth Sreenivasa  */
58*bd28a477SPrashanth Sreenivasa #define	RD_CLOCK_TICK(out, scr1, scr2, label)	\
59*bd28a477SPrashanth Sreenivasa /* CSTYLED */					\
60*bd28a477SPrashanth Sreenivasa 	RD_TICK(out,scr1,scr2,label)
61*bd28a477SPrashanth Sreenivasa 
62*bd28a477SPrashanth Sreenivasa #define	RD_CLOCK_TICK_NO_SUSPEND_CHECK(out, scr1)	\
63*bd28a477SPrashanth Sreenivasa /* CSTYLED */						\
64*bd28a477SPrashanth Sreenivasa 	RD_TICK_NO_SUSPEND_CHECK(out,scr1)
65*bd28a477SPrashanth Sreenivasa 
667c478bd9Sstevel@tonic-gate #endif /* _ASM */
687c478bd9Sstevel@tonic-gate #if defined(CPU_MODULE)
707c478bd9Sstevel@tonic-gate /*
717c478bd9Sstevel@tonic-gate  * Constants used to convert hi-res timestamps into nanoseconds
727c478bd9Sstevel@tonic-gate  * (see <sys/clock.h> file for more information)
737c478bd9Sstevel@tonic-gate  */
7525cf1a30Sjl #if defined(CHEETAH) || defined(HUMMINGBIRD) || defined(OLYMPUS_C)
777c478bd9Sstevel@tonic-gate /*
787c478bd9Sstevel@tonic-gate  * At least 3.9MHz, for slower %stick-based systems.
797c478bd9Sstevel@tonic-gate  */
807c478bd9Sstevel@tonic-gate #define	NSEC_SHIFT	8
827c478bd9Sstevel@tonic-gate #elif defined(SPITFIRE)
847c478bd9Sstevel@tonic-gate /*
857c478bd9Sstevel@tonic-gate  * At least 62.5 MHz, for faster %tick-based systems.
867c478bd9Sstevel@tonic-gate  */
877c478bd9Sstevel@tonic-gate #define	NSEC_SHIFT	4
887c478bd9Sstevel@tonic-gate #define	VTRACE_SHIFT	4
907c478bd9Sstevel@tonic-gate #else
917c478bd9Sstevel@tonic-gate #error "Compiling for CPU_MODULE but no CPU specified"
927c478bd9Sstevel@tonic-gate #endif
94023e71deSHaik Aftandilian /*
95023e71deSHaik Aftandilian  * NOTE: the macros below assume that the various time-related variables
96023e71deSHaik Aftandilian  * (hrestime, hrestime_adj, hres_last_tick, timedelta, nsec_scale, etc)
97023e71deSHaik Aftandilian  * are all stored together on a 64-byte boundary.  The primary motivation
98023e71deSHaik Aftandilian  * is cache performance, but we also take advantage of a convenient side
99023e71deSHaik Aftandilian  * effect: these variables all have the same high 22 address bits, so only
100023e71deSHaik Aftandilian  * one sethi is needed to access them all.
101023e71deSHaik Aftandilian  */
102023e71deSHaik Aftandilian 
103023e71deSHaik Aftandilian /*
104023e71deSHaik Aftandilian  * GET_HRESTIME() returns the value of hrestime, hrestime_adj and the
105023e71deSHaik Aftandilian  * number of nanoseconds since the last clock tick ('nslt').  It also
106023e71deSHaik Aftandilian  * sets 'nano' to the value NANOSEC (one billion).
107023e71deSHaik Aftandilian  *
108023e71deSHaik Aftandilian  * This macro assumes that all registers are globals or outs so they can
109023e71deSHaik Aftandilian  * safely contain 64-bit data, and that it's safe to use the label "5:".
110023e71deSHaik Aftandilian  * Further, this macro calls the NATIVE_TIME_TO_NSEC_SCALE which in turn
111023e71deSHaik Aftandilian  * uses the labels "6:" and "7:"; labels "5:", "6:" and "7:" must not
112023e71deSHaik Aftandilian  * be used across invocations of this macro.
113023e71deSHaik Aftandilian  */
114023e71deSHaik Aftandilian #define	GET_HRESTIME(hrestsec, hrestnsec, adj, nslt, nano, scr, hrlock, \
115023e71deSHaik Aftandilian     gnt1, gnt2) \
116023e71deSHaik Aftandilian 5:	sethi	%hi(hres_lock), scr;					\
117023e71deSHaik Aftandilian 	lduw	[scr + %lo(hres_lock)], hrlock;	/* load clock lock */	\
118023e71deSHaik Aftandilian 	lduw	[scr + %lo(nsec_scale)], nano;	/* tick-to-ns factor */	\
119023e71deSHaik Aftandilian 	andn	hrlock, 1, hrlock;  	/* see comments above! */	\
120023e71deSHaik Aftandilian 	ldx	[scr + %lo(hres_last_tick)], nslt;			\
121023e71deSHaik Aftandilian 	ldn	[scr + %lo(hrestime)], hrestsec; /* load hrestime.sec */\
122023e71deSHaik Aftandilian 	add	scr, %lo(hrestime), hrestnsec;				\
123023e71deSHaik Aftandilian 	ldn	[hrestnsec + CLONGSIZE], hrestnsec;			\
124023e71deSHaik Aftandilian 	GET_NATIVE_TIME(adj, gnt1, gnt2);	/* get current %tick */	\
125023e71deSHaik Aftandilian 	subcc	adj, nslt, nslt; /* nslt = ticks since last clockint */	\
126023e71deSHaik Aftandilian 	movneg	%xcc, %g0, nslt; /* ignore neg delta from tick skew */	\
127023e71deSHaik Aftandilian 	ldx	[scr + %lo(hrestime_adj)], adj; /* load hrestime_adj */	\
128023e71deSHaik Aftandilian 	/* membar #LoadLoad; (see comment (2) above) */			\
129023e71deSHaik Aftandilian 	lduw	[scr + %lo(hres_lock)], scr; /* load clock lock */	\
130023e71deSHaik Aftandilian 	NATIVE_TIME_TO_NSEC_SCALE(nslt, nano, gnt1, NSEC_SHIFT);	\
131023e71deSHaik Aftandilian 	sethi	%hi(NANOSEC), nano;					\
132023e71deSHaik Aftandilian 	xor	hrlock, scr, scr;					\
133023e71deSHaik Aftandilian /* CSTYLED */ 								\
134023e71deSHaik Aftandilian 	brnz,pn	scr, 5b;						\
135023e71deSHaik Aftandilian 	or	nano, %lo(NANOSEC), nano;
136023e71deSHaik Aftandilian 
137023e71deSHaik Aftandilian /*
138023e71deSHaik Aftandilian  * Similar to above, but returns current gethrtime() value in 'base'.
139023e71deSHaik Aftandilian  */
140023e71deSHaik Aftandilian #define	GET_HRTIME(base, now, nslt, scale, scr, hrlock, gnt1, gnt2)	\
141023e71deSHaik Aftandilian 5:	sethi	%hi(hres_lock), scr;					\
142023e71deSHaik Aftandilian 	lduw	[scr + %lo(hres_lock)], hrlock;	/* load clock lock */	\
143023e71deSHaik Aftandilian 	lduw	[scr + %lo(nsec_scale)], scale;	/* tick-to-ns factor */	\
144023e71deSHaik Aftandilian 	andn	hrlock, 1, hrlock;  	/* see comments above! */	\
145023e71deSHaik Aftandilian 	ldx	[scr + %lo(hres_last_tick)], nslt;			\
146023e71deSHaik Aftandilian 	ldx	[scr + %lo(hrtime_base)], base;	/* load hrtime_base */	\
147023e71deSHaik Aftandilian 	GET_NATIVE_TIME(now, gnt1, gnt2);	/* get current %tick */	\
148023e71deSHaik Aftandilian 	subcc	now, nslt, nslt; /* nslt = ticks since last clockint */	\
149023e71deSHaik Aftandilian 	movneg	%xcc, %g0, nslt; /* ignore neg delta from tick skew */	\
150023e71deSHaik Aftandilian 	/* membar #LoadLoad; (see comment (2) above) */			\
151023e71deSHaik Aftandilian 	ld	[scr + %lo(hres_lock)], scr; /* load clock lock */	\
152023e71deSHaik Aftandilian 	NATIVE_TIME_TO_NSEC_SCALE(nslt, scale, gnt1, NSEC_SHIFT);	\
153023e71deSHaik Aftandilian 	xor	hrlock, scr, scr;					\
154023e71deSHaik Aftandilian /* CSTYLED */ 								\
155023e71deSHaik Aftandilian 	brnz,pn	scr, 5b;						\
156023e71deSHaik Aftandilian 	add	base, nslt, base;
157023e71deSHaik Aftandilian 
1587c478bd9Sstevel@tonic-gate #endif /* CPU_MODULE */
1607c478bd9Sstevel@tonic-gate #ifndef _ASM
1627c478bd9Sstevel@tonic-gate #ifdef	_KERNEL
1647c478bd9Sstevel@tonic-gate /*
1657c478bd9Sstevel@tonic-gate  * Hardware watchdog variables and knobs
1667c478bd9Sstevel@tonic-gate  */
1687c478bd9Sstevel@tonic-gate #define	CLK_WATCHDOG_DEFAULT	10	/* 10 seconds */
1707c478bd9Sstevel@tonic-gate extern int	watchdog_enable;
1717c478bd9Sstevel@tonic-gate extern int	watchdog_available;
1727c478bd9Sstevel@tonic-gate extern int	watchdog_activated;
1737c478bd9Sstevel@tonic-gate extern uint_t	watchdog_timeout_seconds;
1757c478bd9Sstevel@tonic-gate /*
1767c478bd9Sstevel@tonic-gate  * tod module name and operations
1777c478bd9Sstevel@tonic-gate  */
1787c478bd9Sstevel@tonic-gate struct tod_ops {
1797c478bd9Sstevel@tonic-gate 	timestruc_t	(*tod_get)(void);
1807c478bd9Sstevel@tonic-gate 	void		(*tod_set)(timestruc_t);
1817c478bd9Sstevel@tonic-gate 	uint_t		(*tod_set_watchdog_timer)(uint_t);
1827c478bd9Sstevel@tonic-gate 	uint_t		(*tod_clear_watchdog_timer)(void);
1837c478bd9Sstevel@tonic-gate 	void		(*tod_set_power_alarm)(timestruc_t);
1847c478bd9Sstevel@tonic-gate 	void		(*tod_clear_power_alarm)(void);
1857c478bd9Sstevel@tonic-gate 	uint64_t	(*tod_get_cpufrequency)(void);
1867c478bd9Sstevel@tonic-gate };
1887c478bd9Sstevel@tonic-gate extern struct tod_ops	tod_ops;
1897c478bd9Sstevel@tonic-gate extern char		*tod_module_name;
191*bd28a477SPrashanth Sreenivasa extern uint64_t gettick_counter(void);
192*bd28a477SPrashanth Sreenivasa #define	CLOCK_TICK_COUNTER() gettick_counter()
193*bd28a477SPrashanth Sreenivasa 
1942df1fe9cSrandyf /*
1952df1fe9cSrandyf  * These defines allow common code to use TOD functions independant
1962df1fe9cSrandyf  * of hardware platform.
1972df1fe9cSrandyf  */
1982df1fe9cSrandyf #define	TODOP_GET(top)		((top).tod_get())
1992df1fe9cSrandyf #define	TODOP_SET(top, ts)	((top).tod_set(ts))
2002df1fe9cSrandyf #define	TODOP_SETWD(top, nsec)	((top).tod_set_watchdog_timer(nsec))
2012df1fe9cSrandyf #define	TODOP_CLRWD(top)	((top).tod_clear_watchdog_timer())
2022df1fe9cSrandyf #define	TODOP_SETWAKE(top, ts)	((top).tod_set_power_alarm(ts))
2032df1fe9cSrandyf #define	TODOP_CLRWAKE(top)	((top).tod_clear_power_alarm())
2057c478bd9Sstevel@tonic-gate #endif	/* _KERNEL */
2077c478bd9Sstevel@tonic-gate #endif	/* _ASM */
2097c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
2107c478bd9Sstevel@tonic-gate }
2117c478bd9Sstevel@tonic-gate #endif
2137c478bd9Sstevel@tonic-gate #endif	/* !_SYS_MACHCLOCK_H */