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 #include <sys/intreg.h> 29 30 #ifdef __cplusplus 31 extern "C" { 32 #endif 33 34 /* 35 * Tick/Stick Register Access 36 * 37 * The following assembly language macros are defined for reading 38 * the %tick and %stick registers as well as reading and writing 39 * the stick compare register. With the exception of trapstat, reads 40 * and writes of these registers all take into account an offset 41 * value which is added to the hardware counter. By default, this 42 * offset is zero. The offsets can only be modified when CPUs are 43 * paused and are only intended to be modified during an OS suspend 44 * operation. 45 * 46 * Since the read of the %tick or %stick is not an atomic operation, 47 * it is possible for a suspend operation to occur between the read 48 * of the hardware register and its offset variable. The default 49 * macros here take this into account by comparing the value of the 50 * offset variable before and after reading the hardware register. 51 * Callers that need to read the %tick register and can guarantee 52 * they will not be preempted can use the RD_TICK_NO_SUSPEND_CHECK 53 * which does not check for native_tick_offset changing. 54 */ 55 #define RD_STICK(out, scr1, scr2, label) \ 56 .rd_stick.label: \ 57 sethi %hi(native_stick_offset), scr1; \ 58 ldx [scr1 + %lo(native_stick_offset)], scr2; \ 59 rd STICK, out; \ 60 ldx [scr1 + %lo(native_stick_offset)], scr1; \ 61 sub scr1, scr2, scr2; \ 62 /* CSTYLED */ \ 63 brnz,pn scr2, .rd_stick.label; \ 64 sllx out, 1, out; \ 65 srlx out, 1, out; \ 66 add out, scr1, out 67 68 /* 69 * These macros on sun4v read the %stick register, because : 70 * 71 * For sun4v platforms %tick can change dynamically *without* kernel 72 * knowledge, due to SP side power & thermal management cases, 73 * which is triggered externally by SP and handled by Hypervisor. 74 * 75 * The frequency of %tick cannot be relied upon by kernel code, 76 * since it changes dynamically without the kernel being aware. 77 * So, always use the constant-frequency %stick on sun4v. 78 */ 79 #define RD_CLOCK_TICK(out, scr1, scr2, label) \ 80 /* CSTYLED */ \ 81 RD_STICK(out,scr1,scr2,label) 82 83 #define RD_STICK_NO_SUSPEND_CHECK(out, scr1) \ 84 sethi %hi(native_stick_offset), scr1; \ 85 ldx [scr1 + %lo(native_stick_offset)], scr1; \ 86 rd STICK, out; \ 87 sllx out, 1, out; \ 88 srlx out, 1, out; \ 89 add out, scr1, out 90 91 #define RD_CLOCK_TICK_NO_SUSPEND_CHECK(out, scr1) \ 92 /* CSTYLED */ \ 93 RD_STICK_NO_SUSPEND_CHECK(out,scr1) 94 95 #ifndef _ASM 96 #ifdef _KERNEL 97 extern u_longlong_t gettick(void); 98 #define CLOCK_TICK_COUNTER() gettick() /* returns %stick */ 99 #endif /* _KERNEL */ 100 #endif /* _ASM */ 101 102 103 #define RD_TICK(out, scr1, scr2, label) \ 104 .rd_tick.label: \ 105 sethi %hi(native_tick_offset), scr1; \ 106 ldx [scr1 + %lo(native_tick_offset)], scr2; \ 107 rd %tick, out; \ 108 ldx [scr1 + %lo(native_tick_offset)], scr1; \ 109 sub scr1, scr2, scr2; \ 110 /* CSTYLED */ \ 111 brnz,pn scr2, .rd_tick.label; \ 112 sllx out, 1, out; \ 113 srlx out, 1, out; \ 114 add out, scr1, out 115 116 #define RD_TICK_NO_SUSPEND_CHECK(out, scr1) \ 117 sethi %hi(native_tick_offset), scr1; \ 118 ldx [scr1 + %lo(native_tick_offset)], scr1; \ 119 rd %tick, out; \ 120 sllx out, 1, out; \ 121 srlx out, 1, out; \ 122 add out, scr1, out 123 124 /* 125 * Read the %stick register without taking the native_stick_offset 126 * into account. 127 */ 128 #define RD_STICK_PHYSICAL(out) \ 129 rd %stick, out 130 131 /* 132 * Read the %tick register without taking the native_tick_offset 133 * into account. Required to be a single instruction, usable in a 134 * delay slot. 135 */ 136 #define RD_TICK_PHYSICAL(out) \ 137 rd %tick, out 138 139 /* 140 * For traptrace, which requires either the %tick or %stick 141 * counter depending on the value of a global variable. 142 * If the kernel variable passed in as 'use_stick' is non-zero, 143 * read the %stick counter into the 'out' register, otherwise, 144 * read the %tick counter. Note the label-less branches. 145 * We do not check for the tick or stick offset variables changing 146 * during the course of the macro's execution and as a result 147 * if a suspend operation occurs between the time the offset 148 * variable is read and the hardware register is read, we will 149 * use an inaccurate traptrace timestamp. 150 */ 151 #define RD_TICKSTICK_FLAG(out, scr1, use_stick) \ 152 sethi %hi(use_stick), scr1; \ 153 lduw [scr1 + %lo(use_stick)], scr1; \ 154 /* CSTYLED */ \ 155 brz,a scr1, .+24; \ 156 rd %tick, out; \ 157 sethi %hi(native_stick_offset), scr1; \ 158 ldx [scr1 + %lo(native_stick_offset)], scr1; \ 159 ba .+16; \ 160 rd STICK, out; \ 161 sethi %hi(native_tick_offset), scr1; \ 162 ldx [scr1 + %lo(native_tick_offset)], scr1; \ 163 sllx out, 1, out; \ 164 srlx out, 1, out; \ 165 add out, scr1, out; 166 167 #define RD_TICKCMPR(out, scr1, scr2, label) \ 168 .rd_stickcmpr.label: \ 169 sethi %hi(native_stick_offset), scr1; \ 170 ldx [scr1 + %lo(native_stick_offset)], scr2; \ 171 rd STICK_COMPARE, out; \ 172 ldx [scr1 + %lo(native_stick_offset)], scr1; \ 173 sub scr1, scr2, scr2; \ 174 /* CSTYLED */ \ 175 brnz,pn scr2, .rd_stickcmpr.label; \ 176 add out, scr1, out 177 178 #define WR_TICKCMPR(in, scr1, scr2, label) \ 179 sethi %hi(native_stick_offset), scr1; \ 180 ldx [scr1 + %lo(native_stick_offset)], scr1; \ 181 sub in, scr1, scr1; \ 182 wr scr1, STICK_COMPARE 183 184 #define GET_NATIVE_TIME(out, scr1, scr2, label) \ 185 /* CSTYLED */ \ 186 RD_STICK(out,scr1,scr2,label) 187 188 /* 189 * Sun4v processors come up with NPT cleared and there is no need to 190 * clear it again. Also, clearing of the NPT cannot be done atomically 191 * on a CMT processor. 192 */ 193 #define CLEARTICKNPT 194 195 #if defined(CPU_MODULE) 196 197 /* 198 * Constants used to convert hi-res timestamps into nanoseconds 199 * (see <sys/clock.h> file for more information) 200 */ 201 202 /* 203 * At least 62.5 MHz, for faster %tick-based systems. 204 */ 205 #define NSEC_SHIFT 4 206 207 /* 208 * NOTE: the macros below assume that the various time-related variables 209 * (hrestime, hrestime_adj, hres_last_tick, timedelta, nsec_scale, etc) 210 * are all stored together on a 64-byte boundary. The primary motivation 211 * is cache performance, but we also take advantage of a convenient side 212 * effect: these variables all have the same high 22 address bits, so only 213 * one sethi is needed to access them all. 214 */ 215 216 /* 217 * GET_HRESTIME() returns the value of hrestime, hrestime_adj and the 218 * number of nanoseconds since the last clock tick ('nslt'). It also 219 * sets 'nano' to the value NANOSEC (one billion). 220 * 221 * This macro assumes that all registers are globals or outs so they can 222 * safely contain 64-bit data, and that it's safe to use the label "5:". 223 * Further, this macro calls the NATIVE_TIME_TO_NSEC_SCALE which in turn 224 * uses the labels "6:" and "7:"; labels "5:", "6:" and "7:" must not 225 * be used across invocations of this macro. 226 */ 227 #define GET_HRESTIME(hrestsec, hrestnsec, adj, nslt, nano, scr, hrlock, \ 228 gnt1, gnt2, label) \ 229 5: sethi %hi(hres_lock), scr; \ 230 lduw [scr + %lo(hres_lock)], hrlock; /* load clock lock */ \ 231 lduw [scr + %lo(nsec_scale)], nano; /* tick-to-ns factor */ \ 232 andn hrlock, 1, hrlock; /* see comments above! */ \ 233 ldx [scr + %lo(hres_last_tick)], nslt; \ 234 ldn [scr + %lo(hrestime)], hrestsec; /* load hrestime.sec */\ 235 add scr, %lo(hrestime), hrestnsec; \ 236 ldn [hrestnsec + CLONGSIZE], hrestnsec; \ 237 /* CSTYLED */ \ 238 GET_NATIVE_TIME(adj,gnt1,gnt2,label); /* get current %stick */ \ 239 subcc adj, nslt, nslt; /* nslt = ticks since last clockint */ \ 240 movneg %xcc, %g0, nslt; /* ignore neg delta from tick skew */ \ 241 ldx [scr + %lo(hrestime_adj)], adj; /* load hrestime_adj */ \ 242 /* membar #LoadLoad; (see comment (2) above) */ \ 243 lduw [scr + %lo(hres_lock)], scr; /* load clock lock */ \ 244 NATIVE_TIME_TO_NSEC_SCALE(nslt, nano, gnt1, NSEC_SHIFT); \ 245 sethi %hi(NANOSEC), nano; \ 246 xor hrlock, scr, scr; \ 247 /* CSTYLED */ \ 248 brnz,pn scr, 5b; \ 249 or nano, %lo(NANOSEC), nano; 250 251 /* 252 * Similar to above, but returns current gethrtime() value in 'base'. 253 */ 254 #define GET_HRTIME(base, now, nslt, scale, scr, hrlock, gnt1, gnt2, label) \ 255 5: sethi %hi(hres_lock), scr; \ 256 lduw [scr + %lo(hres_lock)], hrlock; /* load clock lock */ \ 257 lduw [scr + %lo(nsec_scale)], scale; /* tick-to-ns factor */ \ 258 andn hrlock, 1, hrlock; /* see comments above! */ \ 259 ldx [scr + %lo(hres_last_tick)], nslt; \ 260 ldx [scr + %lo(hrtime_base)], base; /* load hrtime_base */ \ 261 /* CSTYLED */ \ 262 GET_NATIVE_TIME(now,gnt1,gnt2,label); /* get current %stick */ \ 263 subcc now, nslt, nslt; /* nslt = ticks since last clockint */ \ 264 movneg %xcc, %g0, nslt; /* ignore neg delta from tick skew */ \ 265 /* membar #LoadLoad; (see comment (2) above) */ \ 266 ld [scr + %lo(hres_lock)], scr; /* load clock lock */ \ 267 NATIVE_TIME_TO_NSEC_SCALE(nslt, scale, gnt1, NSEC_SHIFT); \ 268 xor hrlock, scr, scr; \ 269 /* CSTYLED */ \ 270 brnz,pn scr, 5b; \ 271 add base, nslt, base; 272 273 #endif /* CPU_MODULE */ 274 275 #ifdef __cplusplus 276 } 277 #endif 278 279 #endif /* !_SYS_MACHCLOCK_H */ 280