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 (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 #ifndef _SYS_MACHCLOCK_H 26 #define _SYS_MACHCLOCK_H 27 28 #ifdef __cplusplus 29 extern "C" { 30 #endif 31 32 #ifdef _ASM 33 /* 34 * Macro to clear the NPT (non-privileged trap) bit in the %tick/%stick 35 * register. Uses %g1-%g4. 36 */ 37 #define CLEARTICKNPT \ 38 sethi %hi(cpu_clearticknpt), %g1; \ 39 jmp %g1 + %lo(cpu_clearticknpt); \ 40 rd %pc, %g4 41 42 #define RD_TICK_NO_SUSPEND_CHECK(out, scr1) \ 43 rdpr %tick, out; \ 44 sllx out, 1, out; \ 45 srlx out, 1, out; 46 47 #define RD_TICK(out, scr1, scr2, label) \ 48 RD_TICK_NO_SUSPEND_CHECK(out, scr1); 49 50 /* 51 * These macros on sun4u read the %tick register, due to : 52 * - %stick does not have enough precision, it's very low frequency 53 * - %stick accesses are very slow on UltraSPARC IIe 54 * Instead, consumers read %tick and scale it by the current stick/tick ratio. 55 * This only works because all cpus in a system change clock ratios 56 * synchronously and the changes are all initiated by the kernel. 57 */ 58 #define RD_CLOCK_TICK(out, scr1, scr2, label) \ 59 /* CSTYLED */ \ 60 RD_TICK(out,scr1,scr2,label) 61 62 #define RD_CLOCK_TICK_NO_SUSPEND_CHECK(out, scr1) \ 63 /* CSTYLED */ \ 64 RD_TICK_NO_SUSPEND_CHECK(out,scr1) 65 66 #endif /* _ASM */ 67 68 #if defined(CPU_MODULE) 69 70 /* 71 * Constants used to convert hi-res timestamps into nanoseconds 72 * (see <sys/clock.h> file for more information) 73 */ 74 75 #if defined(CHEETAH) || defined(HUMMINGBIRD) || defined(OLYMPUS_C) 76 77 /* 78 * At least 3.9MHz, for slower %stick-based systems. 79 */ 80 #define NSEC_SHIFT 8 81 82 #elif defined(SPITFIRE) 83 84 /* 85 * At least 62.5 MHz, for faster %tick-based systems. 86 */ 87 #define NSEC_SHIFT 4 88 #define VTRACE_SHIFT 4 89 90 #else 91 #error "Compiling for CPU_MODULE but no CPU specified" 92 #endif 93 94 /* 95 * NOTE: the macros below assume that the various time-related variables 96 * (hrestime, hrestime_adj, hres_last_tick, timedelta, nsec_scale, etc) 97 * are all stored together on a 64-byte boundary. The primary motivation 98 * is cache performance, but we also take advantage of a convenient side 99 * effect: these variables all have the same high 22 address bits, so only 100 * one sethi is needed to access them all. 101 */ 102 103 /* 104 * GET_HRESTIME() returns the value of hrestime, hrestime_adj and the 105 * number of nanoseconds since the last clock tick ('nslt'). It also 106 * sets 'nano' to the value NANOSEC (one billion). 107 * 108 * This macro assumes that all registers are globals or outs so they can 109 * safely contain 64-bit data, and that it's safe to use the label "5:". 110 * Further, this macro calls the NATIVE_TIME_TO_NSEC_SCALE which in turn 111 * uses the labels "6:" and "7:"; labels "5:", "6:" and "7:" must not 112 * be used across invocations of this macro. 113 */ 114 #define GET_HRESTIME(hrestsec, hrestnsec, adj, nslt, nano, scr, hrlock, \ 115 gnt1, gnt2) \ 116 5: sethi %hi(hres_lock), scr; \ 117 lduw [scr + %lo(hres_lock)], hrlock; /* load clock lock */ \ 118 lduw [scr + %lo(nsec_scale)], nano; /* tick-to-ns factor */ \ 119 andn hrlock, 1, hrlock; /* see comments above! */ \ 120 ldx [scr + %lo(hres_last_tick)], nslt; \ 121 ldn [scr + %lo(hrestime)], hrestsec; /* load hrestime.sec */\ 122 add scr, %lo(hrestime), hrestnsec; \ 123 ldn [hrestnsec + CLONGSIZE], hrestnsec; \ 124 GET_NATIVE_TIME(adj, gnt1, gnt2); /* get current %tick */ \ 125 subcc adj, nslt, nslt; /* nslt = ticks since last clockint */ \ 126 movneg %xcc, %g0, nslt; /* ignore neg delta from tick skew */ \ 127 ldx [scr + %lo(hrestime_adj)], adj; /* load hrestime_adj */ \ 128 /* membar #LoadLoad; (see comment (2) above) */ \ 129 lduw [scr + %lo(hres_lock)], scr; /* load clock lock */ \ 130 NATIVE_TIME_TO_NSEC_SCALE(nslt, nano, gnt1, NSEC_SHIFT); \ 131 sethi %hi(NANOSEC), nano; \ 132 xor hrlock, scr, scr; \ 133 /* CSTYLED */ \ 134 brnz,pn scr, 5b; \ 135 or nano, %lo(NANOSEC), nano; 136 137 /* 138 * Similar to above, but returns current gethrtime() value in 'base'. 139 */ 140 #define GET_HRTIME(base, now, nslt, scale, scr, hrlock, gnt1, gnt2) \ 141 5: sethi %hi(hres_lock), scr; \ 142 lduw [scr + %lo(hres_lock)], hrlock; /* load clock lock */ \ 143 lduw [scr + %lo(nsec_scale)], scale; /* tick-to-ns factor */ \ 144 andn hrlock, 1, hrlock; /* see comments above! */ \ 145 ldx [scr + %lo(hres_last_tick)], nslt; \ 146 ldx [scr + %lo(hrtime_base)], base; /* load hrtime_base */ \ 147 GET_NATIVE_TIME(now, gnt1, gnt2); /* get current %tick */ \ 148 subcc now, nslt, nslt; /* nslt = ticks since last clockint */ \ 149 movneg %xcc, %g0, nslt; /* ignore neg delta from tick skew */ \ 150 /* membar #LoadLoad; (see comment (2) above) */ \ 151 ld [scr + %lo(hres_lock)], scr; /* load clock lock */ \ 152 NATIVE_TIME_TO_NSEC_SCALE(nslt, scale, gnt1, NSEC_SHIFT); \ 153 xor hrlock, scr, scr; \ 154 /* CSTYLED */ \ 155 brnz,pn scr, 5b; \ 156 add base, nslt, base; 157 158 #endif /* CPU_MODULE */ 159 160 #ifndef _ASM 161 162 #ifdef _KERNEL 163 164 /* 165 * Hardware watchdog variables and knobs 166 */ 167 168 #define CLK_WATCHDOG_DEFAULT 10 /* 10 seconds */ 169 170 extern int watchdog_enable; 171 extern int watchdog_available; 172 extern int watchdog_activated; 173 extern uint_t watchdog_timeout_seconds; 174 175 /* 176 * tod module name and operations 177 */ 178 struct tod_ops { 179 timestruc_t (*tod_get)(void); 180 void (*tod_set)(timestruc_t); 181 uint_t (*tod_set_watchdog_timer)(uint_t); 182 uint_t (*tod_clear_watchdog_timer)(void); 183 void (*tod_set_power_alarm)(timestruc_t); 184 void (*tod_clear_power_alarm)(void); 185 uint64_t (*tod_get_cpufrequency)(void); 186 }; 187 188 extern struct tod_ops tod_ops; 189 extern char *tod_module_name; 190 191 extern uint64_t gettick_counter(void); 192 #define CLOCK_TICK_COUNTER() gettick_counter() 193 194 /* 195 * These defines allow common code to use TOD functions independant 196 * of hardware platform. 197 */ 198 #define TODOP_GET(top) ((top).tod_get()) 199 #define TODOP_SET(top, ts) ((top).tod_set(ts)) 200 #define TODOP_SETWD(top, nsec) ((top).tod_set_watchdog_timer(nsec)) 201 #define TODOP_CLRWD(top) ((top).tod_clear_watchdog_timer()) 202 #define TODOP_SETWAKE(top, ts) ((top).tod_set_power_alarm(ts)) 203 #define TODOP_CLRWAKE(top) ((top).tod_clear_power_alarm()) 204 205 #endif /* _KERNEL */ 206 207 #endif /* _ASM */ 208 209 #ifdef __cplusplus 210 } 211 #endif 212 213 #endif /* !_SYS_MACHCLOCK_H */ 214