2 * Copyright (c) 2017 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
28 #include <stdatomic.h>
29 #include <mach/mach_time.h>
30 #include <mach/clock_types.h>
31 #include <kern/misc_protos.h>
32 #include <kern/clock.h>
33 #include <kern/remote_time.h>
35 #include <kern/locks.h>
36 #include <sys/kdebug.h>
37 #include <machine/machine_routines.h>
38 #include <kern/assert.h>
39 #include <kern/kern_types.h>
40 #include <kern/thread.h>
41 #include <machine/commpage.h>
43 #if CONFIG_MACH_BRIDGE_SEND_TIME
45 uint32_t bt_enable_flag
= 0;
46 lck_spin_t
*bt_maintenance_lock
= NULL
;
47 _Atomic
uint32_t bt_init_flag
= 0;
49 void mach_bridge_timer_maintenance(void);
50 void mach_bridge_timer_init(void);
51 uint32_t mach_bridge_timer_enable(uint32_t new_value
, int change
);
54 * When CONFIG_MACH_BRIDGE_SEND_TIME is defined, it is expected
55 * that a machine-specific timestamp sending routine such as
56 * void mach_bridge_send_timestamp(uint64_t); has also been defined.
58 extern void mach_bridge_send_timestamp(uint64_t);
61 mach_bridge_timer_maintenance()
67 lck_spin_lock(bt_maintenance_lock
);
68 if (!bt_enable_flag
) {
71 mach_bridge_send_timestamp(0);
74 lck_spin_unlock(bt_maintenance_lock
);
78 * This function should be called only once from the callback
79 * registration function
82 mach_bridge_timer_init(void)
84 assert(!bt_init_flag
);
85 /* Initialize the lock */
86 static lck_grp_t
*bt_lck_grp
= NULL
;
87 bt_lck_grp
= lck_grp_alloc_init("bridgetimestamp", LCK_GRP_ATTR_NULL
);
88 bt_maintenance_lock
= lck_spin_alloc_init(bt_lck_grp
, NULL
);
92 * If change = 0, return the current value of bridge_timer_enable
93 * If change = 1, update bridge_timer_enable and return the updated
97 mach_bridge_timer_enable(uint32_t new_value
, int change
)
99 uint32_t current_value
= 0;
100 assert(bt_init_flag
== 1);
101 lck_spin_lock(bt_maintenance_lock
);
103 bt_enable_flag
= new_value
;
105 current_value
= bt_enable_flag
;
106 lck_spin_unlock(bt_maintenance_lock
);
107 return current_value
;
110 #endif /* CONFIG_MACH_BRIDGE_SEND_TIME */
112 #if CONFIG_MACH_BRIDGE_RECV_TIME
113 #include <machine/machine_remote_time.h>
116 * functions used by machine-specific code
117 * that implements CONFIG_MACH_BRIDGE_RECV_TIME
119 void mach_bridge_add_timestamp(uint64_t remote_timestamp
, uint64_t local_timestamp
);
120 void bt_calibration_thread_start(void);
121 lck_spin_t
*ts_conversion_lock
= NULL
;
123 /* function called by sysctl */
124 struct bt_params
bt_params_get_latest(void);
127 * Platform specific bridge time receiving interface.
128 * These variables should be exported by the platform specific time receiving code.
130 extern lck_spin_t
*bt_spin_lock
;
131 extern _Atomic
uint32_t bt_init_flag
;
133 static uint64_t received_local_timestamp
= 0;
134 static uint64_t received_remote_timestamp
= 0;
136 * Buffer the previous timestamp pairs and rate
137 * It is protected by the ts_conversion_lock
139 #define BT_PARAMS_COUNT 10
140 static struct bt_params bt_params_hist
[BT_PARAMS_COUNT
] = {};
141 static int bt_params_idx
= -1;
144 bt_params_add(struct bt_params
*params
)
146 lck_spin_assert(ts_conversion_lock
, LCK_ASSERT_OWNED
);
148 bt_params_idx
= (bt_params_idx
+ 1) % BT_PARAMS_COUNT
;
149 bt_params_hist
[bt_params_idx
] = *params
;
152 static inline struct bt_params
*
153 bt_params_find(uint64_t local_ts
)
155 lck_spin_assert(ts_conversion_lock
, LCK_ASSERT_OWNED
);
157 int idx
= bt_params_idx
;
162 if (local_ts
>= bt_params_hist
[idx
].base_local_ts
) {
163 return &bt_params_hist
[idx
];
166 idx
= BT_PARAMS_COUNT
- 1;
168 } while (idx
!= bt_params_idx
);
174 bt_params_get_latest(void)
176 struct bt_params latest_params
= {};
178 /* Check if ts_converison_lock has been initialized */
179 if (atomic_load(&bt_init_flag
)) {
180 lck_spin_lock(ts_conversion_lock
);
181 if (bt_params_idx
>= 0) {
182 latest_params
= bt_params_hist
[bt_params_idx
];
184 lck_spin_unlock(ts_conversion_lock
);
186 return latest_params
;
190 * Conditions: bt_spin_lock held and called from primary interrupt context
193 mach_bridge_add_timestamp(uint64_t remote_timestamp
, uint64_t local_timestamp
)
195 lck_spin_assert(bt_spin_lock
, LCK_ASSERT_OWNED
);
197 /* sleep/wake might return the same mach_absolute_time as the previous timestamp pair */
198 if ((received_local_timestamp
== local_timestamp
) ||
199 (received_remote_timestamp
== remote_timestamp
)) {
203 received_local_timestamp
= local_timestamp
;
204 received_remote_timestamp
= remote_timestamp
;
205 thread_wakeup((event_t
)bt_params_hist
);
209 mach_bridge_compute_rate(uint64_t new_local_ts
, uint64_t new_remote_ts
,
210 uint64_t old_local_ts
, uint64_t old_remote_ts
)
212 int64_t rdiff
= (int64_t)new_remote_ts
- (int64_t)old_remote_ts
;
213 int64_t ldiff
= (int64_t)new_local_ts
- (int64_t)old_local_ts
;
214 double calc_rate
= ((double)rdiff
) / ldiff
;
218 #define MAX_RECALCULATE_COUNT 8
219 #define CUMULATIVE_RATE_DECAY_CONSTANT 0.01
220 #define CUMULATIVE_RATE_WEIGHT 0.99
221 #define INITIAL_RATE 1.0
222 #define MIN_INITIAL_SAMPLE_COUNT 10
223 #define MAX_INITIAL_SAMPLE_COUNT 50
224 #define MAX_SKIP_RESET_COUNT 2
225 #define MIN_LOCAL_TS_DISTANCE_NS 100000000 /* 100 ms */
226 #define MAX_LOCAL_TS_DISTANCE_NS 350000000 /* 350 ms */
227 #define TS_PAIR_MISMATCH_THRESHOLD_NS 50000000 /* 50 ms */
228 #define MAX_TS_PAIR_MISMATCHES 5
229 #define MAX_TS_PAIR_MISMATCH_RESET_COUNT 3
230 #define MIN_OBSERVED_RATE 0.8
231 #define MAX_OBSERVED_RATE 1.2
234 bt_calibration_thread(void)
236 static uint64_t prev_local_ts
= 0, prev_remote_ts
= 0, curr_local_ts
= 0, curr_remote_ts
= 0;
237 static uint64_t prev_received_local_ts
= 0, prev_received_remote_ts
= 0;
238 static double cumulative_rate
= INITIAL_RATE
;
239 static uint32_t initial_sample_count
= 1;
240 static uint32_t max_initial_sample_count
= MAX_INITIAL_SAMPLE_COUNT
;
241 static uint32_t skip_reset_count
= MAX_SKIP_RESET_COUNT
;
242 int recalculate_count
= 1;
243 static bool reset
= false;
245 static bool skip_rcv_ts
= false;
246 static uint64_t ts_pair_mismatch
= 0;
247 static uint32_t ts_pair_mismatch_reset_count
= 0;
248 spl_t s
= splsched();
249 lck_spin_lock(bt_spin_lock
);
250 if (!received_remote_timestamp
) {
251 if (PE_parse_boot_argn("rt_ini_count", &max_initial_sample_count
,
252 sizeof(uint32_t)) == TRUE
) {
253 if (max_initial_sample_count
< MIN_INITIAL_SAMPLE_COUNT
) {
254 max_initial_sample_count
= MIN_INITIAL_SAMPLE_COUNT
;
257 /* Nothing to do the first time */
261 * The values in bt_params are recalculated every time a new timestamp
262 * pair is received. Firstly, both timestamps are converted to nanoseconds.
263 * The current and previous timestamp pairs are used to compute the
264 * observed_rate of the two clocks w.r.t each other. For the first
265 * MIN_INITIAL_SAMPLE_COUNT number of pairs, the cumulative_rate is a simple
266 * average of the observed_rate. For the later pairs, the cumulative_rate
267 * is updated using exponential moving average of the observed_rate.
268 * The current and bt_params' base timestamp pairs are used to compute
269 * the rate_from_base. This value ensures that the bt_params base
270 * timestamp pair curve doesn't stay parallel to the observed timestamp
271 * pair curve, rather moves in the direction of the observed timestamp curve.
272 * The bt_params.rate is computed as a weighted average of the cumulative_rate
273 * and the rate_from_base. For each current local timestamp, the remote_time
274 * is predicted using the previous values of bt_params. After computing the new
275 * bt_params.rate, bt_params.base_remote_time is set to this predicted value
276 * and bt_params.base_local_time is set to the current local timestamp.
279 assertf(recalculate_count
<= MAX_RECALCULATE_COUNT
, "bt_caliberation_thread: recalculate \
280 invocation exceeds MAX_RECALCULATE_COUNT");
282 if ((received_remote_timestamp
== BT_RESET_SENTINEL_TS
) || (received_remote_timestamp
== BT_WAKE_SENTINEL_TS
)) {
283 KDBG(MACHDBG_CODE(DBG_MACH_CLOCK
, MACH_BRIDGE_RESET_TS
), received_local_timestamp
, received_remote_timestamp
, 1);
285 skip_reset_count
= MAX_SKIP_RESET_COUNT
;
286 ts_pair_mismatch_reset_count
= 0;
288 } else if (received_remote_timestamp
== BT_SLEEP_SENTINEL_TS
) {
290 } else if (!received_local_timestamp
) {
291 /* If the local timestamp isn't accurately captured, the received value will be ignored */
296 /* Keep a copy of the prev timestamps to compute distance */
297 prev_received_local_ts
= curr_local_ts
;
298 prev_received_remote_ts
= curr_remote_ts
;
300 uint64_t curr_local_abs
= received_local_timestamp
;
301 absolutetime_to_nanoseconds(curr_local_abs
, &curr_local_ts
);
302 curr_remote_ts
= received_remote_timestamp
;
304 /* Prevent unusual rate changes caused by delayed timestamps */
305 uint64_t local_diff
= curr_local_ts
- prev_received_local_ts
;
306 if (!(reset
|| sleep
) && ((local_diff
< MIN_LOCAL_TS_DISTANCE_NS
) ||
307 (!skip_rcv_ts
&& (local_diff
> MAX_LOCAL_TS_DISTANCE_NS
)))) {
308 /* Skip the current timestamp */
309 KDBG(MACHDBG_CODE(DBG_MACH_CLOCK
, MACH_BRIDGE_SKIP_TS
), curr_local_ts
, curr_remote_ts
,
310 prev_received_local_ts
);
314 /* Use the prev copy of timestamps only if the distance is acceptable */
315 prev_local_ts
= prev_received_local_ts
;
316 prev_remote_ts
= prev_received_remote_ts
;
318 lck_spin_unlock(bt_spin_lock
);
321 struct bt_params bt_params
= {};
323 lck_spin_lock(ts_conversion_lock
);
325 if (skip_reset_count
> 0) {
326 KDBG(MACHDBG_CODE(DBG_MACH_CLOCK
, MACH_BRIDGE_SKIP_TS
), curr_local_ts
, curr_remote_ts
,
327 prev_local_ts
, skip_reset_count
);
331 bt_params
.base_local_ts
= curr_local_ts
;
332 bt_params
.base_remote_ts
= curr_remote_ts
;
333 bt_params
.rate
= cumulative_rate
;
336 ts_pair_mismatch
= 0;
337 initial_sample_count
= 1;
339 KDBG(MACHDBG_CODE(DBG_MACH_CLOCK
, MACH_BRIDGE_RESET_TS
), curr_local_ts
, curr_remote_ts
, 2);
341 absolutetime_to_nanoseconds(mach_absolute_time(), &bt_params
.base_local_ts
);
342 bt_params
.base_remote_ts
= 0;
346 struct bt_params bt_params_snapshot
= {};
347 if (bt_params_idx
>= 0) {
348 bt_params_snapshot
= bt_params_hist
[bt_params_idx
];
350 lck_spin_unlock(ts_conversion_lock
);
351 if (bt_params_snapshot
.rate
== 0.0) {
353 * The rate should never be 0 because we always expect a reset/wake
354 * sentinel after sleep, followed by valid timestamp pair data that
355 * will be handled by the reset clause (above). However, we should
356 * not rely on a paired version of the remote OS - we could actually
357 * be running a completely different OS! Treat a timestamp after
358 * a sleep as a reset condition.
361 skip_reset_count
= MAX_SKIP_RESET_COUNT
;
362 ts_pair_mismatch_reset_count
= 0;
363 KDBG(MACHDBG_CODE(DBG_MACH_CLOCK
, MACH_BRIDGE_RESET_TS
), curr_local_ts
, curr_remote_ts
, 3);
365 lck_spin_lock(bt_spin_lock
);
369 /* Check if the predicted remote timestamp is within the expected current remote timestamp range */
370 uint64_t pred_remote_ts
= mach_bridge_compute_timestamp(curr_local_ts
, &bt_params_snapshot
);
372 if (initial_sample_count
>= max_initial_sample_count
) {
373 if (pred_remote_ts
> curr_remote_ts
) {
374 diff
= pred_remote_ts
- curr_remote_ts
;
376 diff
= curr_remote_ts
- pred_remote_ts
;
378 if (diff
> TS_PAIR_MISMATCH_THRESHOLD_NS
) {
380 KDBG(MACHDBG_CODE(DBG_MACH_CLOCK
, MACH_BRIDGE_TS_MISMATCH
), curr_local_ts
,
381 curr_remote_ts
, pred_remote_ts
, ts_pair_mismatch
);
383 ts_pair_mismatch
= 0;
385 if (ts_pair_mismatch
> MAX_TS_PAIR_MISMATCHES
) {
386 #if (DEVELOPMENT || DEBUG)
387 if (ts_pair_mismatch_reset_count
== MAX_TS_PAIR_MISMATCH_RESET_COUNT
) {
388 panic("remote_time: timestamp pair mismatch exceeded limit");
390 #endif /* (DEVELOPMENT || DEBUG) */
392 ts_pair_mismatch_reset_count
++;
393 KDBG(MACHDBG_CODE(DBG_MACH_CLOCK
, MACH_BRIDGE_RESET_TS
), curr_local_ts
, curr_remote_ts
, 4);
395 lck_spin_lock(bt_spin_lock
);
399 double observed_rate
, rate_from_base
, new_rate
;
400 observed_rate
= mach_bridge_compute_rate(curr_local_ts
, curr_remote_ts
, prev_local_ts
, prev_remote_ts
);
401 /* Log bad observed rates and skip the timestamp pair */
402 if ((observed_rate
< MIN_OBSERVED_RATE
) || (observed_rate
> MAX_OBSERVED_RATE
)) {
403 KDBG(MACHDBG_CODE(DBG_MACH_CLOCK
, MACH_BRIDGE_OBSV_RATE
), *(uint64_t *)((void *)&observed_rate
));
404 ts_pair_mismatch
= ts_pair_mismatch
> 0 ? (ts_pair_mismatch
- 1) : 0;
406 lck_spin_lock(bt_spin_lock
);
409 if (initial_sample_count
<= MIN_INITIAL_SAMPLE_COUNT
) {
410 initial_sample_count
++;
411 cumulative_rate
= cumulative_rate
+ (observed_rate
- cumulative_rate
) / initial_sample_count
;
413 if (initial_sample_count
< max_initial_sample_count
) {
414 initial_sample_count
++;
416 cumulative_rate
= cumulative_rate
+ CUMULATIVE_RATE_DECAY_CONSTANT
* (observed_rate
- cumulative_rate
);
418 rate_from_base
= mach_bridge_compute_rate(curr_local_ts
, curr_remote_ts
, bt_params_snapshot
.base_local_ts
,
419 bt_params_snapshot
.base_remote_ts
);
420 new_rate
= CUMULATIVE_RATE_WEIGHT
* cumulative_rate
+ (1 - CUMULATIVE_RATE_WEIGHT
) * rate_from_base
;
422 * Acquire the lock first to ensure that bt_params.base_local_ts is always
423 * greater than the last value of now captured by mach_bridge_remote_time.
424 * This ensures that we always use the same parameters to compute remote
425 * timestamp for a given local timestamp.
427 lck_spin_lock(ts_conversion_lock
);
428 absolutetime_to_nanoseconds(mach_absolute_time(), &bt_params
.base_local_ts
);
429 bt_params
.base_remote_ts
= mach_bridge_compute_timestamp(bt_params
.base_local_ts
, &bt_params_snapshot
);
430 bt_params
.rate
= new_rate
;
432 bt_params_add(&bt_params
);
433 commpage_set_remotetime_params(bt_params
.rate
, bt_params
.base_local_ts
, bt_params
.base_remote_ts
);
434 KDBG(MACHDBG_CODE(DBG_MACH_CLOCK
, MACH_BRIDGE_TS_PARAMS
), bt_params
.base_local_ts
,
435 bt_params
.base_remote_ts
, *(uint64_t *)((void *)&bt_params
.rate
));
438 lck_spin_unlock(ts_conversion_lock
);
441 lck_spin_lock(bt_spin_lock
);
442 /* Check if a new timestamp pair was received */
443 if (received_local_timestamp
!= curr_local_abs
) {
448 assert_wait((event_t
)bt_params_hist
, THREAD_UNINT
);
449 lck_spin_unlock(bt_spin_lock
);
451 thread_block((thread_continue_t
)bt_calibration_thread
);
455 bt_calibration_thread_start(void)
458 kern_return_t result
= kernel_thread_start_priority((thread_continue_t
)bt_calibration_thread
,
459 NULL
, BASEPRI_KERNEL
, &thread
);
460 if (result
!= KERN_SUCCESS
) {
461 panic("mach_bridge_add_timestamp: thread_timestamp_calibration");
463 thread_deallocate(thread
);
466 #endif /* CONFIG_MACH_BRIDGE_RECV_TIME */
469 * mach_bridge_remote_time
471 * This function is used to predict the remote CPU's clock time, given
474 * If local_timestamp = 0, then the remote_timestamp is calculated
475 * corresponding to the current mach_absolute_time. Monotonicity of
476 * predicted time is guaranteed only for recent local_timestamp values
477 * lesser than the current mach_absolute_time upto 1 second.
479 * If CONFIG_MACH_BRIDGE_SEND_TIME is true, then the function is compiled
480 * for the remote CPU. If CONFIG_MACH_BRIDGE_RECV_TIME is true, then the
481 * the function is compiled for the local CPU. Both config options cannot
482 * be true simultaneously.
485 mach_bridge_remote_time(uint64_t local_timestamp
)
487 #if defined(CONFIG_MACH_BRIDGE_SEND_TIME)
488 #if !defined(CONFIG_MACH_BRIDGE_RECV_TIME)
489 /* only send side of the bridge is defined: no translation needed */
490 if (!local_timestamp
) {
491 return mach_absolute_time();
495 #error "You cannot define both sides of the bridge!"
496 #endif /* !defined(CONFIG_MACH_BRIDGE_RECV_TIME) */
498 #if !defined(CONFIG_MACH_BRIDGE_RECV_TIME)
499 /* neither the send or receive side of the bridge is defined: echo the input */
500 return local_timestamp
;
502 if (!atomic_load(&bt_init_flag
)) {
506 lck_spin_lock(ts_conversion_lock
);
507 uint64_t now
= mach_absolute_time();
509 uint64_t remote_timestamp
= 0;
510 uint64_t local_timestamp_ns
= 0;
511 if (!local_timestamp
) {
512 local_timestamp
= now
;
513 } else if (local_timestamp
> now
) {
516 absolutetime_to_nanoseconds(local_timestamp
, &local_timestamp_ns
);
517 struct bt_params
*params
= bt_params_find(local_timestamp_ns
);
518 remote_timestamp
= mach_bridge_compute_timestamp(local_timestamp_ns
, params
);
521 lck_spin_unlock(ts_conversion_lock
);
522 KDBG(MACHDBG_CODE(DBG_MACH_CLOCK
, MACH_BRIDGE_REMOTE_TIME
), local_timestamp
, remote_timestamp
, now
);
523 return remote_timestamp
;
524 #endif /* !defined(CONFIG_MACH_BRIDGE_RECV_TIME) */
525 #endif /* defined(CONFIG_MACH_BRIDGE_SEND_TIME) */