1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #ifndef _SYS_MACHCLOCK_H 27 #define _SYS_MACHCLOCK_H 28 29 #ifdef __cplusplus 30 extern "C" { 31 #endif 32 33 #ifdef _ASM 34 /* 35 * Macro to clear the NPT (non-privileged trap) bit in the %tick/%stick 36 * register. Uses %g1-%g4. 37 */ 38 #define CLEARTICKNPT \ 39 sethi %hi(cpu_clearticknpt), %g1; \ 40 jmp %g1 + %lo(cpu_clearticknpt); \ 41 rd %pc, %g4 42 43 #define RD_TICK_NO_SUSPEND_CHECK(out, scr1) \ 44 rdpr %tick, out; \ 45 sllx out, 1, out; \ 46 srlx out, 1, out; 47 48 #define RD_TICK(out, scr1, scr2, label) \ 49 RD_TICK_NO_SUSPEND_CHECK(out, scr1); 50 51 #endif /* _ASM */ 52 53 #if defined(CPU_MODULE) 54 55 /* 56 * Constants used to convert hi-res timestamps into nanoseconds 57 * (see <sys/clock.h> file for more information) 58 */ 59 60 #if defined(CHEETAH) || defined(HUMMINGBIRD) || defined(OLYMPUS_C) 61 62 /* 63 * At least 3.9MHz, for slower %stick-based systems. 64 */ 65 #define NSEC_SHIFT 8 66 67 #elif defined(SPITFIRE) 68 69 /* 70 * At least 62.5 MHz, for faster %tick-based systems. 71 */ 72 #define NSEC_SHIFT 4 73 #define VTRACE_SHIFT 4 74 75 #else 76 #error "Compiling for CPU_MODULE but no CPU specified" 77 #endif 78 79 /* 80 * NOTE: the macros below assume that the various time-related variables 81 * (hrestime, hrestime_adj, hres_last_tick, timedelta, nsec_scale, etc) 82 * are all stored together on a 64-byte boundary. The primary motivation 83 * is cache performance, but we also take advantage of a convenient side 84 * effect: these variables all have the same high 22 address bits, so only 85 * one sethi is needed to access them all. 86 */ 87 88 /* 89 * GET_HRESTIME() returns the value of hrestime, hrestime_adj and the 90 * number of nanoseconds since the last clock tick ('nslt'). It also 91 * sets 'nano' to the value NANOSEC (one billion). 92 * 93 * This macro assumes that all registers are globals or outs so they can 94 * safely contain 64-bit data, and that it's safe to use the label "5:". 95 * Further, this macro calls the NATIVE_TIME_TO_NSEC_SCALE which in turn 96 * uses the labels "6:" and "7:"; labels "5:", "6:" and "7:" must not 97 * be used across invocations of this macro. 98 */ 99 #define GET_HRESTIME(hrestsec, hrestnsec, adj, nslt, nano, scr, hrlock, \ 100 gnt1, gnt2) \ 101 5: sethi %hi(hres_lock), scr; \ 102 lduw [scr + %lo(hres_lock)], hrlock; /* load clock lock */ \ 103 lduw [scr + %lo(nsec_scale)], nano; /* tick-to-ns factor */ \ 104 andn hrlock, 1, hrlock; /* see comments above! */ \ 105 ldx [scr + %lo(hres_last_tick)], nslt; \ 106 ldn [scr + %lo(hrestime)], hrestsec; /* load hrestime.sec */\ 107 add scr, %lo(hrestime), hrestnsec; \ 108 ldn [hrestnsec + CLONGSIZE], hrestnsec; \ 109 GET_NATIVE_TIME(adj, gnt1, gnt2); /* get current %tick */ \ 110 subcc adj, nslt, nslt; /* nslt = ticks since last clockint */ \ 111 movneg %xcc, %g0, nslt; /* ignore neg delta from tick skew */ \ 112 ldx [scr + %lo(hrestime_adj)], adj; /* load hrestime_adj */ \ 113 /* membar #LoadLoad; (see comment (2) above) */ \ 114 lduw [scr + %lo(hres_lock)], scr; /* load clock lock */ \ 115 NATIVE_TIME_TO_NSEC_SCALE(nslt, nano, gnt1, NSEC_SHIFT); \ 116 sethi %hi(NANOSEC), nano; \ 117 xor hrlock, scr, scr; \ 118 /* CSTYLED */ \ 119 brnz,pn scr, 5b; \ 120 or nano, %lo(NANOSEC), nano; 121 122 /* 123 * Similar to above, but returns current gethrtime() value in 'base'. 124 */ 125 #define GET_HRTIME(base, now, nslt, scale, scr, hrlock, gnt1, gnt2) \ 126 5: sethi %hi(hres_lock), scr; \ 127 lduw [scr + %lo(hres_lock)], hrlock; /* load clock lock */ \ 128 lduw [scr + %lo(nsec_scale)], scale; /* tick-to-ns factor */ \ 129 andn hrlock, 1, hrlock; /* see comments above! */ \ 130 ldx [scr + %lo(hres_last_tick)], nslt; \ 131 ldx [scr + %lo(hrtime_base)], base; /* load hrtime_base */ \ 132 GET_NATIVE_TIME(now, gnt1, gnt2); /* get current %tick */ \ 133 subcc now, nslt, nslt; /* nslt = ticks since last clockint */ \ 134 movneg %xcc, %g0, nslt; /* ignore neg delta from tick skew */ \ 135 /* membar #LoadLoad; (see comment (2) above) */ \ 136 ld [scr + %lo(hres_lock)], scr; /* load clock lock */ \ 137 NATIVE_TIME_TO_NSEC_SCALE(nslt, scale, gnt1, NSEC_SHIFT); \ 138 xor hrlock, scr, scr; \ 139 /* CSTYLED */ \ 140 brnz,pn scr, 5b; \ 141 add base, nslt, base; 142 143 #endif /* CPU_MODULE */ 144 145 #ifndef _ASM 146 147 #ifdef _KERNEL 148 149 /* 150 * Hardware watchdog variables and knobs 151 */ 152 153 #define CLK_WATCHDOG_DEFAULT 10 /* 10 seconds */ 154 155 extern int watchdog_enable; 156 extern int watchdog_available; 157 extern int watchdog_activated; 158 extern uint_t watchdog_timeout_seconds; 159 160 /* 161 * tod module name and operations 162 */ 163 struct tod_ops { 164 timestruc_t (*tod_get)(void); 165 void (*tod_set)(timestruc_t); 166 uint_t (*tod_set_watchdog_timer)(uint_t); 167 uint_t (*tod_clear_watchdog_timer)(void); 168 void (*tod_set_power_alarm)(timestruc_t); 169 void (*tod_clear_power_alarm)(void); 170 uint64_t (*tod_get_cpufrequency)(void); 171 }; 172 173 extern struct tod_ops tod_ops; 174 extern char *tod_module_name; 175 176 /* 177 * These defines allow common code to use TOD functions independant 178 * of hardware platform. 179 */ 180 #define TODOP_GET(top) ((top).tod_get()) 181 #define TODOP_SET(top, ts) ((top).tod_set(ts)) 182 #define TODOP_SETWD(top, nsec) ((top).tod_set_watchdog_timer(nsec)) 183 #define TODOP_CLRWD(top) ((top).tod_clear_watchdog_timer()) 184 #define TODOP_SETWAKE(top, ts) ((top).tod_set_power_alarm(ts)) 185 #define TODOP_CLRWAKE(top) ((top).tod_clear_power_alarm()) 186 187 #endif /* _KERNEL */ 188 189 #endif /* _ASM */ 190 191 #ifdef __cplusplus 192 } 193 #endif 194 195 #endif /* !_SYS_MACHCLOCK_H */ 196