1 /*
2 * Copyright (c) 2007-2021 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * @OSF_COPYRIGHT@
30 */
31 /*
32 * @APPLE_FREE_COPYRIGHT@
33 */
34 /*
35 * File: arm/rtclock.c
36 * Purpose: Routines for handling the machine dependent
37 * real-time clock.
38 */
39
40 #include <mach/mach_types.h>
41
42 #include <kern/clock.h>
43 #include <kern/thread.h>
44 #include <kern/macro_help.h>
45 #include <kern/spl.h>
46 #include <kern/timer_queue.h>
47
48 #include <kern/host_notify.h>
49
50 #include <machine/commpage.h>
51 #include <machine/machine_routines.h>
52 #include <machine/config.h>
53 #include <arm/exception.h>
54 #include <arm/cpu_data_internal.h>
55 #if __arm64__
56 #include <arm64/proc_reg.h>
57 #else
58 #error Unsupported arch
59 #endif
60 #include <arm/rtclock.h>
61
62 #include <IOKit/IOPlatformExpert.h>
63 #include <libkern/OSAtomic.h>
64
65 #include <sys/kdebug.h>
66
67 #define MAX_TIMEBASE_TRIES 10
68
69 int rtclock_init(void);
70
71 static int
72 deadline_to_decrementer(uint64_t deadline,
73 uint64_t now);
74 static void
75 timebase_callback(struct timebase_freq_t * freq);
76
77 #if DEVELOPMENT || DEBUG
78 uint32_t timebase_validation = 0;
79 #endif
80
81 /*
82 * Configure the real-time clock device at boot
83 */
84 void
rtclock_early_init(void)85 rtclock_early_init(void)
86 {
87 PE_register_timebase_callback(timebase_callback);
88 #if DEVELOPMENT || DEBUG
89 uint32_t tmp_mv = 1;
90
91 #if defined(APPLE_ARM64_ARCH_FAMILY)
92 /* Enable MAT validation on A0 hardware by default. */
93 timebase_validation = ml_get_topology_info()->chip_revision == CPU_VERSION_A0;
94 #endif
95
96 if (kern_feature_override(KF_MATV_OVRD)) {
97 timebase_validation = 0;
98 }
99 if (PE_parse_boot_argn("timebase_validation", &tmp_mv, sizeof(tmp_mv))) {
100 timebase_validation = tmp_mv;
101 }
102 #endif
103 }
104
105 static void
timebase_callback(struct timebase_freq_t * freq)106 timebase_callback(struct timebase_freq_t * freq)
107 {
108 unsigned long numer, denom;
109 uint64_t t64_1, t64_2;
110 uint32_t divisor;
111
112 if (freq->timebase_den < 1 || freq->timebase_den > 4 ||
113 freq->timebase_num < freq->timebase_den) {
114 panic("rtclock timebase_callback: invalid constant %ld / %ld",
115 freq->timebase_num, freq->timebase_den);
116 }
117
118 denom = freq->timebase_num;
119 numer = freq->timebase_den * NSEC_PER_SEC;
120 // reduce by the greatest common denominator to minimize overflow
121 if (numer > denom) {
122 t64_1 = numer;
123 t64_2 = denom;
124 } else {
125 t64_1 = denom;
126 t64_2 = numer;
127 }
128 while (t64_2 != 0) {
129 uint64_t temp = t64_2;
130 t64_2 = t64_1 % t64_2;
131 t64_1 = temp;
132 }
133 numer /= t64_1;
134 denom /= t64_1;
135
136 rtclock_timebase_const.numer = (uint32_t)numer;
137 rtclock_timebase_const.denom = (uint32_t)denom;
138 divisor = (uint32_t)(freq->timebase_num / freq->timebase_den);
139
140 rtclock_sec_divisor = divisor;
141 rtclock_usec_divisor = divisor / USEC_PER_SEC;
142 }
143
144 /*
145 * Initialize the system clock device for the current cpu
146 */
147 int
rtclock_init(void)148 rtclock_init(void)
149 {
150 uint64_t abstime;
151 cpu_data_t * cdp;
152
153 clock_timebase_init();
154 ml_init_lock_timeout();
155
156 cdp = getCpuDatap();
157
158 abstime = mach_absolute_time();
159 cdp->rtcPop = EndOfAllTime; /* Init Pop time */
160 timer_resync_deadlines(); /* Start the timers going */
161
162 return 1;
163 }
164
165
166 uint64_t
mach_absolute_time(void)167 mach_absolute_time(void)
168 {
169 #if DEVELOPMENT || DEBUG
170 if (__improbable(timebase_validation)) {
171 #if __ARM_ARCH_8_6__ || HAS_ACNTVCT
172 static _Atomic uint64_t s_last_absolute_time = 1;
173
174 uint64_t old_absolute_time = os_atomic_load(&s_last_absolute_time, relaxed);
175
176 /*
177 * Because this timebase read is nonspeculative, it cannot begin reading
178 * the timebase value until after the load of the old value completes.
179 */
180
181 if (old_absolute_time == 0) {
182 timebase_validation = 0; // we know it's bad, now prevent nested panics
183 panic("old_absolute_time was 0");
184 }
185
186 uint64_t new_absolute_time = ml_get_timebase();
187
188 if (old_absolute_time > new_absolute_time) {
189 timebase_validation = 0; // prevent nested panics
190 panic("mach_absolute_time returning non-monotonically increasing value 0x%llx (old value 0x%llx)",
191 new_absolute_time, old_absolute_time);
192 }
193
194 if (old_absolute_time < new_absolute_time) {
195 /* read again, to pretest the atomic max */
196 uint64_t pretest_absolute_time = os_atomic_load(&s_last_absolute_time, relaxed);
197 if (pretest_absolute_time < new_absolute_time) {
198 uint64_t fresh_last_absolute_time = os_atomic_max_orig(&s_last_absolute_time, new_absolute_time, relaxed);
199
200 if (fresh_last_absolute_time != pretest_absolute_time) {
201 /*
202 * Someone else published a newer time after we loaded s_last_absolute_time.
203 * Enforce that our timebase is not behind this new one.
204 * We can't compare it with our previous timebase read, as it is too old.
205 */
206
207 uint64_t newest_absolute_time = ml_get_timebase();
208
209 if (fresh_last_absolute_time > newest_absolute_time) {
210 timebase_validation = 0; // prevent nested panics
211 panic("mach_absolute_time returning non-monotonically increasing value 0x%llx (old values 0x%llx, 0x%llx, 0x%llx, 0x%llx)\n",
212 newest_absolute_time, fresh_last_absolute_time, pretest_absolute_time, old_absolute_time, new_absolute_time);
213 }
214 }
215 }
216 }
217
218 return new_absolute_time;
219
220 #else /* !(__ARM_ARCH_8_6__ || HAS_ACNTVCT) */
221 static volatile uint64_t s_last_absolute_time = 0;
222 uint64_t new_absolute_time, old_absolute_time;
223 int attempts = 0;
224
225 /* ARM 64: We need a dsb here to ensure that the load of s_last_absolute_time
226 * completes before the timebase read. Were the load to complete after the
227 * timebase read, there would be a window for another CPU to update
228 * s_last_absolute_time and leave us in an inconsistent state. Consider the
229 * following interleaving:
230 *
231 * Let s_last_absolute_time = t0
232 * CPU0: Read timebase at t1
233 * CPU1: Read timebase at t2
234 * CPU1: Update s_last_absolute_time to t2
235 * CPU0: Load completes
236 * CPU0: Update s_last_absolute_time to t1
237 *
238 * This would cause the assertion to fail even though time did not go
239 * backwards. Thus, we use a dsb to guarantee completion of the load before
240 * the timebase read.
241 */
242 do {
243 attempts++;
244 old_absolute_time = s_last_absolute_time;
245
246 __builtin_arm_dsb(DSB_ISHLD);
247
248 new_absolute_time = ml_get_timebase();
249 } while (attempts < MAX_TIMEBASE_TRIES && !OSCompareAndSwap64(old_absolute_time, new_absolute_time, &s_last_absolute_time));
250
251 if (attempts < MAX_TIMEBASE_TRIES && old_absolute_time > new_absolute_time) {
252 timebase_validation = 0; // we know it's bad, now prevent nested panics
253 panic("mach_absolute_time returning non-monotonically increasing value 0x%llx (old value 0x%llx\n)",
254 new_absolute_time, old_absolute_time);
255 }
256 return new_absolute_time;
257 #endif /* __ARM_ARCH_8_6__ || HAS_ACNTVCT */
258 }
259 #endif /* DEVELOPMENT || DEBUG */
260
261 return ml_get_timebase();
262 }
263
264 uint64_t
mach_approximate_time(void)265 mach_approximate_time(void)
266 {
267 #if __ARM_TIME__ || __ARM_TIME_TIMEBASE_ONLY__ || __arm64__
268 /* Hardware supports a fast timestamp, so grab it without asserting monotonicity */
269 return ml_get_timebase();
270 #else
271 processor_t processor;
272 uint64_t approx_time;
273
274 disable_preemption();
275 processor = current_processor();
276 approx_time = processor->last_dispatch;
277 enable_preemption();
278
279 return approx_time;
280 #endif
281 }
282
283 void
clock_get_system_microtime(clock_sec_t * secs,clock_usec_t * microsecs)284 clock_get_system_microtime(clock_sec_t * secs,
285 clock_usec_t * microsecs)
286 {
287 absolutetime_to_microtime(mach_absolute_time(), secs, microsecs);
288 }
289
290 void
clock_get_system_nanotime(clock_sec_t * secs,clock_nsec_t * nanosecs)291 clock_get_system_nanotime(clock_sec_t * secs,
292 clock_nsec_t * nanosecs)
293 {
294 uint64_t abstime;
295 uint64_t t64;
296
297 abstime = mach_absolute_time();
298 *secs = (t64 = abstime / rtclock_sec_divisor);
299 abstime -= (t64 * rtclock_sec_divisor);
300
301 *nanosecs = (clock_nsec_t)((abstime * NSEC_PER_SEC) / rtclock_sec_divisor);
302 }
303
304 void
clock_gettimeofday_set_commpage(uint64_t abstime,uint64_t sec,uint64_t frac,uint64_t scale,uint64_t tick_per_sec)305 clock_gettimeofday_set_commpage(uint64_t abstime,
306 uint64_t sec,
307 uint64_t frac,
308 uint64_t scale,
309 uint64_t tick_per_sec)
310 {
311 commpage_set_timestamp(abstime, sec, frac, scale, tick_per_sec);
312 }
313
314 void
clock_timebase_info(mach_timebase_info_t info)315 clock_timebase_info(mach_timebase_info_t info)
316 {
317 *info = rtclock_timebase_const;
318 }
319
320 /*
321 * Real-time clock device interrupt.
322 */
323 void
rtclock_intr(__unused unsigned int is_user_context)324 rtclock_intr(__unused unsigned int is_user_context)
325 {
326 uint64_t abstime;
327 cpu_data_t * cdp;
328 struct arm_saved_state * regs;
329 unsigned int user_mode;
330 uintptr_t pc;
331
332 cdp = getCpuDatap();
333
334 cdp->cpu_stat.timer_cnt++;
335 SCHED_STATS_INC(timer_pop_count);
336
337 assert(!ml_get_interrupts_enabled());
338
339 abstime = mach_absolute_time();
340
341 if (cdp->cpu_idle_pop != 0x0ULL) {
342 if ((cdp->rtcPop - abstime) < cdp->cpu_idle_latency) {
343 cdp->cpu_idle_pop = 0x0ULL;
344 while (abstime < cdp->rtcPop) {
345 abstime = mach_absolute_time();
346 }
347 } else {
348 ClearIdlePop(FALSE);
349 }
350 }
351
352 if ((regs = cdp->cpu_int_state)) {
353 pc = get_saved_state_pc(regs);
354
355 #if __arm64__
356 user_mode = PSR64_IS_USER(get_saved_state_cpsr(regs));
357 #endif
358 } else {
359 pc = 0;
360 user_mode = 0;
361 }
362 if (abstime >= cdp->rtcPop) {
363 /* Log the interrupt service latency (-ve value expected by tool) */
364 KDBG_RELEASE(DECR_TRAP_LATENCY | DBG_FUNC_NONE,
365 -(abstime - cdp->rtcPop),
366 user_mode ? pc : VM_KERNEL_UNSLIDE(pc), user_mode);
367 }
368
369 /* call the generic etimer */
370 timer_intr(user_mode, pc);
371 }
372
373 static int
deadline_to_decrementer(uint64_t deadline,uint64_t now)374 deadline_to_decrementer(uint64_t deadline,
375 uint64_t now)
376 {
377 uint64_t delt;
378
379 if (deadline <= now) {
380 return DECREMENTER_MIN;
381 } else {
382 delt = deadline - now;
383
384 return (delt >= (DECREMENTER_MAX + 1)) ? DECREMENTER_MAX : ((delt >= (DECREMENTER_MIN + 1)) ? (int)delt : DECREMENTER_MIN);
385 }
386 }
387
388 /*
389 * Request a decrementer pop
390 */
391 int
setPop(uint64_t time)392 setPop(uint64_t time)
393 {
394 int delay_time;
395 uint64_t current_time;
396 cpu_data_t * cdp;
397
398 cdp = getCpuDatap();
399 current_time = mach_absolute_time();
400
401 delay_time = deadline_to_decrementer(time, current_time);
402 cdp->rtcPop = delay_time + current_time;
403
404 ml_set_decrementer((uint32_t) delay_time);
405
406 return delay_time;
407 }
408
409 /*
410 * Request decrementer Idle Pop. Return true if set
411 */
412 boolean_t
SetIdlePop(void)413 SetIdlePop(void)
414 {
415 int delay_time;
416 uint64_t time;
417 uint64_t current_time;
418 cpu_data_t * cdp;
419
420 cdp = getCpuDatap();
421 current_time = mach_absolute_time();
422
423 if (((cdp->rtcPop < current_time) ||
424 (cdp->rtcPop - current_time) < cdp->cpu_idle_latency)) {
425 return FALSE;
426 }
427
428 time = cdp->rtcPop - cdp->cpu_idle_latency;
429
430 delay_time = deadline_to_decrementer(time, current_time);
431 cdp->cpu_idle_pop = delay_time + current_time;
432 ml_set_decrementer((uint32_t) delay_time);
433
434 return TRUE;
435 }
436
437 /*
438 * Clear decrementer Idle Pop
439 */
440 void
ClearIdlePop(boolean_t wfi)441 ClearIdlePop(
442 boolean_t wfi)
443 {
444 cpu_data_t * cdp;
445
446 cdp = getCpuDatap();
447 cdp->cpu_idle_pop = 0x0ULL;
448
449 /*
450 * Don't update the HW timer if there's a pending
451 * interrupt (we can lose interrupt assertion);
452 * we want to take the interrupt right now and update
453 * the deadline from the handler).
454 *
455 * ARM64_TODO: consider this more carefully.
456 */
457 if (!(wfi && ml_get_timer_pending())) {
458 setPop(cdp->rtcPop);
459 }
460 }
461
462 void
absolutetime_to_microtime(uint64_t abstime,clock_sec_t * secs,clock_usec_t * microsecs)463 absolutetime_to_microtime(uint64_t abstime,
464 clock_sec_t * secs,
465 clock_usec_t * microsecs)
466 {
467 uint64_t t64;
468
469 *secs = t64 = abstime / rtclock_sec_divisor;
470 abstime -= (t64 * rtclock_sec_divisor);
471
472 *microsecs = (uint32_t)(abstime / rtclock_usec_divisor);
473 }
474
475 void
absolutetime_to_nanoseconds(uint64_t abstime,uint64_t * result)476 absolutetime_to_nanoseconds(uint64_t abstime,
477 uint64_t * result)
478 {
479 uint64_t t64;
480
481 *result = (t64 = abstime / rtclock_sec_divisor) * NSEC_PER_SEC;
482 abstime -= (t64 * rtclock_sec_divisor);
483 *result += (abstime * NSEC_PER_SEC) / rtclock_sec_divisor;
484 }
485
486 void
nanoseconds_to_absolutetime(uint64_t nanosecs,uint64_t * result)487 nanoseconds_to_absolutetime(uint64_t nanosecs,
488 uint64_t * result)
489 {
490 uint64_t t64;
491
492 *result = (t64 = nanosecs / NSEC_PER_SEC) * rtclock_sec_divisor;
493 nanosecs -= (t64 * NSEC_PER_SEC);
494 *result += (nanosecs * rtclock_sec_divisor) / NSEC_PER_SEC;
495 }
496
497 void
nanotime_to_absolutetime(clock_sec_t secs,clock_nsec_t nanosecs,uint64_t * result)498 nanotime_to_absolutetime(clock_sec_t secs,
499 clock_nsec_t nanosecs,
500 uint64_t * result)
501 {
502 *result = ((uint64_t) secs * rtclock_sec_divisor) +
503 ((uint64_t) nanosecs * rtclock_sec_divisor) / NSEC_PER_SEC;
504 }
505
506 void
clock_interval_to_absolutetime_interval(uint32_t interval,uint32_t scale_factor,uint64_t * result)507 clock_interval_to_absolutetime_interval(uint32_t interval,
508 uint32_t scale_factor,
509 uint64_t * result)
510 {
511 uint64_t nanosecs = (uint64_t) interval * scale_factor;
512 uint64_t t64;
513
514 *result = (t64 = nanosecs / NSEC_PER_SEC) * rtclock_sec_divisor;
515 nanosecs -= (t64 * NSEC_PER_SEC);
516 *result += (nanosecs * rtclock_sec_divisor) / NSEC_PER_SEC;
517 }
518
519 void
machine_delay_until(uint64_t interval,uint64_t deadline)520 machine_delay_until(uint64_t interval,
521 uint64_t deadline)
522 {
523 #pragma unused(interval)
524 uint64_t now;
525
526 do {
527 __builtin_arm_wfe();
528 now = mach_absolute_time();
529 } while (now < deadline);
530 }
531