xref: /xnu-10063.121.3/osfmk/kern/remote_time.c (revision 2c2f96dc2b9a4408a43d3150ae9c105355ca3daa)
1 /*
2  * Copyright (c) 2017-2020 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 #include <mach/mach_time.h>
29 #include <mach/clock_types.h>
30 #include <kern/misc_protos.h>
31 #include <kern/clock.h>
32 #include <kern/remote_time.h>
33 #include <kern/spl.h>
34 #include <kern/locks.h>
35 #include <sys/kdebug.h>
36 #include <machine/machine_routines.h>
37 #include <kern/assert.h>
38 #include <kern/kern_types.h>
39 #include <kern/thread.h>
40 #include <machine/commpage.h>
41 #include <machine/atomic.h>
42 
43 LCK_GRP_DECLARE(bt_lck_grp, "bridge timestamp");
44 LCK_SPIN_DECLARE(bt_spin_lock, &bt_lck_grp);
45 LCK_SPIN_DECLARE(bt_ts_conversion_lock, &bt_lck_grp);
46 LCK_SPIN_DECLARE(bt_maintenance_lock, &bt_lck_grp);
47 
48 #if CONFIG_MACH_BRIDGE_SEND_TIME
49 
50 uint32_t bt_enable_flag = 0;
51 _Atomic uint32_t bt_init_flag = 0;
52 
53 void mach_bridge_timer_maintenance(void);
54 uint32_t mach_bridge_timer_enable(uint32_t new_value, int change);
55 
56 /*
57  * When CONFIG_MACH_BRIDGE_SEND_TIME is defined, it is expected
58  * that a machine-specific timestamp sending routine such as
59  * void mach_bridge_send_timestamp(uint64_t); has also been defined.
60  */
61 extern void mach_bridge_send_timestamp(uint64_t);
62 
63 void
mach_bridge_timer_maintenance(void)64 mach_bridge_timer_maintenance(void)
65 {
66 	if (!os_atomic_load(&bt_init_flag, acquire)) {
67 		return;
68 	}
69 
70 	lck_spin_lock(&bt_maintenance_lock);
71 	if (!bt_enable_flag) {
72 		goto done;
73 	}
74 	mach_bridge_send_timestamp(0);
75 
76 done:
77 	lck_spin_unlock(&bt_maintenance_lock);
78 }
79 
80 /*
81  * If change = 0, return the current value of bridge_timer_enable
82  * If change = 1, update bridge_timer_enable and return the updated
83  * value
84  */
85 uint32_t
mach_bridge_timer_enable(uint32_t new_value,int change)86 mach_bridge_timer_enable(uint32_t new_value, int change)
87 {
88 	uint32_t current_value = 0;
89 	assert(os_atomic_load(&bt_init_flag, relaxed));
90 	lck_spin_lock(&bt_maintenance_lock);
91 	if (change) {
92 		bt_enable_flag = new_value;
93 	}
94 	current_value = bt_enable_flag;
95 	lck_spin_unlock(&bt_maintenance_lock);
96 	return current_value;
97 }
98 
99 #endif /* CONFIG_MACH_BRIDGE_SEND_TIME */
100 
101 #if CONFIG_MACH_BRIDGE_RECV_TIME
102 #include <machine/machine_remote_time.h>
103 
104 /*
105  * functions used by machine-specific code
106  * that implements CONFIG_MACH_BRIDGE_RECV_TIME
107  */
108 void mach_bridge_add_timestamp(uint64_t remote_timestamp, uint64_t local_timestamp);
109 void bt_calibration_thread_start(void);
110 void bt_params_add(struct bt_params *params);
111 
112 /* function called by sysctl */
113 struct bt_params bt_params_get_latest(void);
114 
115 /*
116  * Platform specific bridge time receiving interface.
117  * These variables should be exported by the platform specific time receiving code.
118  */
119 extern _Atomic uint32_t bt_init_flag;
120 
121 static uint64_t received_local_timestamp = 0;
122 static uint64_t received_remote_timestamp = 0;
123 /*
124  * Buffer the previous timestamp pairs and rate
125  * It is protected by the bt_ts_conversion_lock
126  */
127 #define BT_PARAMS_COUNT 10
128 static struct bt_params bt_params_hist[BT_PARAMS_COUNT] = {};
129 static int bt_params_idx = -1;
130 
131 void
bt_params_add(struct bt_params * params)132 bt_params_add(struct bt_params *params)
133 {
134 	lck_spin_assert(&bt_ts_conversion_lock, LCK_ASSERT_OWNED);
135 
136 	bt_params_idx = (bt_params_idx + 1) % BT_PARAMS_COUNT;
137 	bt_params_hist[bt_params_idx] = *params;
138 }
139 
140 #if defined(XNU_TARGET_OS_BRIDGE)
141 static inline struct bt_params*
bt_params_find(uint64_t local_ts)142 bt_params_find(uint64_t local_ts)
143 {
144 	lck_spin_assert(&bt_ts_conversion_lock, LCK_ASSERT_OWNED);
145 
146 	int idx = bt_params_idx;
147 	if (idx < 0) {
148 		return NULL;
149 	}
150 	do {
151 		if (local_ts >= bt_params_hist[idx].base_local_ts) {
152 			return &bt_params_hist[idx];
153 		}
154 		if (--idx < 0) {
155 			idx = BT_PARAMS_COUNT - 1;
156 		}
157 	} while (idx != bt_params_idx);
158 
159 	return NULL;
160 }
161 #endif /* defined(XNU_TARGET_OS_BRIDGE) */
162 
163 static inline struct bt_params
bt_params_get_latest_locked(void)164 bt_params_get_latest_locked(void)
165 {
166 	lck_spin_assert(&bt_ts_conversion_lock, LCK_ASSERT_OWNED);
167 
168 	struct bt_params latest_params = {};
169 	if (bt_params_idx >= 0) {
170 		latest_params = bt_params_hist[bt_params_idx];
171 	}
172 
173 	return latest_params;
174 }
175 
176 struct bt_params
bt_params_get_latest(void)177 bt_params_get_latest(void)
178 {
179 	struct bt_params latest_params = {};
180 
181 	/* Check if ts_converison_lock has been initialized */
182 	if (os_atomic_load(&bt_init_flag, acquire)) {
183 		lck_spin_lock(&bt_ts_conversion_lock);
184 		latest_params = bt_params_get_latest_locked();
185 		lck_spin_unlock(&bt_ts_conversion_lock);
186 	}
187 	return latest_params;
188 }
189 
190 /*
191  * Conditions: bt_spin_lock held and called from primary interrupt context
192  */
193 void
mach_bridge_add_timestamp(uint64_t remote_timestamp,uint64_t local_timestamp)194 mach_bridge_add_timestamp(uint64_t remote_timestamp, uint64_t local_timestamp)
195 {
196 	lck_spin_assert(&bt_spin_lock, LCK_ASSERT_OWNED);
197 
198 	/* sleep/wake might return the same mach_absolute_time as the previous timestamp pair */
199 	if ((received_local_timestamp == local_timestamp) ||
200 	    (received_remote_timestamp == remote_timestamp)) {
201 		return;
202 	}
203 
204 	received_local_timestamp = local_timestamp;
205 	received_remote_timestamp = remote_timestamp;
206 	thread_wakeup((event_t)bt_params_hist);
207 }
208 
209 static double
mach_bridge_compute_rate(uint64_t new_local_ts,uint64_t new_remote_ts,uint64_t old_local_ts,uint64_t old_remote_ts)210 mach_bridge_compute_rate(uint64_t new_local_ts, uint64_t new_remote_ts,
211     uint64_t old_local_ts, uint64_t old_remote_ts)
212 {
213 	int64_t rdiff = (int64_t)new_remote_ts - (int64_t)old_remote_ts;
214 	int64_t ldiff = (int64_t)new_local_ts - (int64_t)old_local_ts;
215 	double calc_rate = ((double)rdiff) / (double)ldiff;
216 	return calc_rate;
217 }
218 
219 #define MAX_RECALCULATE_COUNT 8
220 #define CUMULATIVE_RATE_DECAY_CONSTANT 0.01
221 #define CUMULATIVE_RATE_WEIGHT 0.99
222 #define INITIAL_RATE 1.0
223 #define MIN_INITIAL_SAMPLE_COUNT 10
224 #define MAX_INITIAL_SAMPLE_COUNT 50
225 #define MAX_SKIP_RESET_COUNT 2
226 #define MIN_LOCAL_TS_DISTANCE_NS 100000000 /* 100 ms */
227 #define MAX_LOCAL_TS_DISTANCE_NS 350000000 /* 350 ms */
228 #define TS_PAIR_MISMATCH_THRESHOLD_NS 50000000 /* 50 ms */
229 #define MAX_TS_PAIR_MISMATCHES 5
230 #define MAX_TS_PAIR_MISMATCH_RESET_COUNT 3
231 #define MIN_OBSERVED_RATE 0.8
232 #define MAX_OBSERVED_RATE 1.2
233 
234 static void
bt_calibration_thread(void)235 bt_calibration_thread(void)
236 {
237 	static uint64_t prev_local_ts = 0, prev_remote_ts = 0, curr_local_ts = 0, curr_remote_ts = 0;
238 	static uint64_t prev_received_local_ts = 0, prev_received_remote_ts = 0;
239 	static double cumulative_rate = INITIAL_RATE;
240 	static uint32_t initial_sample_count = 1;
241 	static uint32_t max_initial_sample_count = MAX_INITIAL_SAMPLE_COUNT;
242 	static uint32_t skip_reset_count = MAX_SKIP_RESET_COUNT;
243 	int recalculate_count = 1;
244 	static bool reset = false;
245 	bool sleep = false;
246 	static bool skip_rcv_ts = false;
247 	static uint64_t ts_pair_mismatch = 0;
248 	static uint32_t ts_pair_mismatch_reset_count = 0;
249 	spl_t s = splsched();
250 	lck_spin_lock(&bt_spin_lock);
251 	if (!received_remote_timestamp) {
252 		if (PE_parse_boot_argn("rt_ini_count", &max_initial_sample_count,
253 		    sizeof(uint32_t)) == TRUE) {
254 			if (max_initial_sample_count < MIN_INITIAL_SAMPLE_COUNT) {
255 				max_initial_sample_count = MIN_INITIAL_SAMPLE_COUNT;
256 			}
257 		}
258 		/* Nothing to do the first time */
259 		goto block;
260 	}
261 	/*
262 	 * The values in bt_params are recalculated every time a new timestamp
263 	 * pair is received. Firstly, both timestamps are converted to nanoseconds.
264 	 * The current and previous timestamp pairs are used to compute the
265 	 * observed_rate of the two clocks w.r.t each other. For the first
266 	 * MIN_INITIAL_SAMPLE_COUNT number of pairs, the cumulative_rate is a simple
267 	 * average of the observed_rate. For the later pairs, the cumulative_rate
268 	 * is updated using exponential moving average of the observed_rate.
269 	 * The current and bt_params' base timestamp pairs are used to compute
270 	 * the rate_from_base. This value ensures that the bt_params base
271 	 * timestamp pair curve doesn't stay parallel to the observed timestamp
272 	 * pair curve, rather moves in the direction of the observed timestamp curve.
273 	 * The bt_params.rate is computed as a weighted average of the cumulative_rate
274 	 * and the rate_from_base. For each current local timestamp, the remote_time
275 	 * is predicted using the previous values of bt_params. After computing the new
276 	 * bt_params.rate, bt_params.base_remote_time is set to this predicted value
277 	 * and bt_params.base_local_time is set to the current local timestamp.
278 	 */
279 recalculate:
280 	assertf(recalculate_count <= MAX_RECALCULATE_COUNT, "bt_caliberation_thread: recalculate \
281 					invocation exceeds MAX_RECALCULATE_COUNT");
282 
283 	if ((received_remote_timestamp == BT_RESET_SENTINEL_TS) || (received_remote_timestamp == BT_WAKE_SENTINEL_TS)) {
284 		KDBG(MACHDBG_CODE(DBG_MACH_CLOCK, MACH_BRIDGE_RESET_TS), received_local_timestamp, received_remote_timestamp, 1);
285 		reset = true;
286 		skip_reset_count = MAX_SKIP_RESET_COUNT;
287 		ts_pair_mismatch_reset_count = 0;
288 		goto block;
289 	} else if (received_remote_timestamp == BT_SLEEP_SENTINEL_TS) {
290 		sleep = true;
291 	} else if (!received_local_timestamp) {
292 		/* If the local timestamp isn't accurately captured, the received value will be ignored */
293 		skip_rcv_ts = true;
294 		goto block;
295 	}
296 
297 	/* Keep a copy of the prev timestamps to compute distance */
298 	prev_received_local_ts = curr_local_ts;
299 	prev_received_remote_ts = curr_remote_ts;
300 
301 	uint64_t curr_local_abs = received_local_timestamp;
302 	absolutetime_to_nanoseconds(curr_local_abs, &curr_local_ts);
303 	curr_remote_ts = received_remote_timestamp;
304 
305 	/* Prevent unusual rate changes caused by delayed timestamps */
306 	uint64_t local_diff = curr_local_ts - prev_received_local_ts;
307 	if (!(reset || sleep) && ((local_diff < MIN_LOCAL_TS_DISTANCE_NS) ||
308 	    (!skip_rcv_ts && (local_diff > MAX_LOCAL_TS_DISTANCE_NS)))) {
309 		/* Skip the current timestamp */
310 		KDBG(MACHDBG_CODE(DBG_MACH_CLOCK, MACH_BRIDGE_SKIP_TS), curr_local_ts, curr_remote_ts,
311 		    prev_received_local_ts);
312 		goto block;
313 	} else {
314 		skip_rcv_ts = false;
315 		/* Use the prev copy of timestamps only if the distance is acceptable */
316 		prev_local_ts = prev_received_local_ts;
317 		prev_remote_ts = prev_received_remote_ts;
318 	}
319 	lck_spin_unlock(&bt_spin_lock);
320 	splx(s);
321 
322 	struct bt_params bt_params = {};
323 
324 	lck_spin_lock(&bt_ts_conversion_lock);
325 	if (reset) {
326 		if (skip_reset_count > 0) {
327 			KDBG(MACHDBG_CODE(DBG_MACH_CLOCK, MACH_BRIDGE_SKIP_TS), curr_local_ts, curr_remote_ts,
328 			    prev_local_ts, skip_reset_count);
329 			skip_reset_count--;
330 			goto skip_reset;
331 		}
332 		bt_params.base_local_ts = curr_local_ts;
333 		bt_params.base_remote_ts = curr_remote_ts;
334 		bt_params.rate = cumulative_rate;
335 		prev_local_ts = 0;
336 		prev_remote_ts = 0;
337 		ts_pair_mismatch = 0;
338 		initial_sample_count = 1;
339 		reset = false;
340 		KDBG(MACHDBG_CODE(DBG_MACH_CLOCK, MACH_BRIDGE_RESET_TS), curr_local_ts, curr_remote_ts, 2);
341 	} else if (sleep) {
342 		absolutetime_to_nanoseconds(mach_absolute_time(), &bt_params.base_local_ts);
343 		bt_params.base_remote_ts = 0;
344 		bt_params.rate = 0;
345 		sleep = false;
346 	} else {
347 		struct bt_params bt_params_snapshot = {};
348 		if (bt_params_idx >= 0) {
349 			bt_params_snapshot = bt_params_hist[bt_params_idx];
350 		}
351 		lck_spin_unlock(&bt_ts_conversion_lock);
352 		if (bt_params_snapshot.rate == 0.0) {
353 			/*
354 			 * The rate should never be 0 because we always expect a reset/wake
355 			 * sentinel after sleep, followed by valid timestamp pair data that
356 			 * will be handled by the reset clause (above). However, we should
357 			 * not rely on a paired version of the remote OS - we could actually
358 			 * be running a completely different OS! Treat a timestamp after
359 			 * a sleep as a reset condition.
360 			 */
361 			reset = true;
362 			skip_reset_count = MAX_SKIP_RESET_COUNT;
363 			ts_pair_mismatch_reset_count = 0;
364 			KDBG(MACHDBG_CODE(DBG_MACH_CLOCK, MACH_BRIDGE_RESET_TS), curr_local_ts, curr_remote_ts, 3);
365 			s = splsched();
366 			lck_spin_lock(&bt_spin_lock);
367 			goto block;
368 		}
369 
370 		/* Check if the predicted remote timestamp is within the expected current remote timestamp range */
371 		uint64_t pred_remote_ts = mach_bridge_compute_timestamp(curr_local_ts, &bt_params_snapshot);
372 		uint64_t diff = 0;
373 		if (initial_sample_count >= max_initial_sample_count) {
374 			if (pred_remote_ts > curr_remote_ts) {
375 				diff = pred_remote_ts - curr_remote_ts;
376 			} else {
377 				diff = curr_remote_ts - pred_remote_ts;
378 			}
379 			if (diff > TS_PAIR_MISMATCH_THRESHOLD_NS) {
380 				ts_pair_mismatch++;
381 				KDBG(MACHDBG_CODE(DBG_MACH_CLOCK, MACH_BRIDGE_TS_MISMATCH), curr_local_ts,
382 				    curr_remote_ts, pred_remote_ts, ts_pair_mismatch);
383 			} else {
384 				ts_pair_mismatch = 0;
385 			}
386 			if (ts_pair_mismatch > MAX_TS_PAIR_MISMATCHES) {
387 #if (DEVELOPMENT || DEBUG)
388 				if (ts_pair_mismatch_reset_count == MAX_TS_PAIR_MISMATCH_RESET_COUNT) {
389 					panic("remote_time: timestamp pair mismatch exceeded limit");
390 				}
391 #endif /* (DEVELOPMENT || DEBUG) */
392 				reset = true;
393 				ts_pair_mismatch_reset_count++;
394 				KDBG(MACHDBG_CODE(DBG_MACH_CLOCK, MACH_BRIDGE_RESET_TS), curr_local_ts, curr_remote_ts, 4);
395 				s = splsched();
396 				lck_spin_lock(&bt_spin_lock);
397 				goto block;
398 			}
399 		}
400 		double observed_rate, rate_from_base, new_rate;
401 		observed_rate = mach_bridge_compute_rate(curr_local_ts, curr_remote_ts, prev_local_ts, prev_remote_ts);
402 		/* Log bad observed rates and skip the timestamp pair */
403 		if ((observed_rate < MIN_OBSERVED_RATE) || (observed_rate > MAX_OBSERVED_RATE)) {
404 			KDBG(MACHDBG_CODE(DBG_MACH_CLOCK, MACH_BRIDGE_OBSV_RATE), *(uint64_t *)((void *)&observed_rate));
405 			ts_pair_mismatch = ts_pair_mismatch > 0 ? (ts_pair_mismatch - 1) : 0;
406 			s = splsched();
407 			lck_spin_lock(&bt_spin_lock);
408 			goto block;
409 		}
410 		if (initial_sample_count <= MIN_INITIAL_SAMPLE_COUNT) {
411 			initial_sample_count++;
412 			cumulative_rate = cumulative_rate + (observed_rate - cumulative_rate) / initial_sample_count;
413 		} else {
414 			if (initial_sample_count < max_initial_sample_count) {
415 				initial_sample_count++;
416 			}
417 			cumulative_rate = cumulative_rate + CUMULATIVE_RATE_DECAY_CONSTANT * (observed_rate - cumulative_rate);
418 		}
419 		rate_from_base = mach_bridge_compute_rate(curr_local_ts, curr_remote_ts, bt_params_snapshot.base_local_ts,
420 		    bt_params_snapshot.base_remote_ts);
421 		new_rate = CUMULATIVE_RATE_WEIGHT * cumulative_rate + (1 - CUMULATIVE_RATE_WEIGHT) * rate_from_base;
422 		/*
423 		 * Acquire the lock first to ensure that bt_params.base_local_ts is always
424 		 * greater than the last value of now captured by mach_bridge_remote_time.
425 		 * This ensures that we always use the same parameters to compute remote
426 		 * timestamp for a given local timestamp.
427 		 */
428 		lck_spin_lock(&bt_ts_conversion_lock);
429 		absolutetime_to_nanoseconds(mach_absolute_time(), &bt_params.base_local_ts);
430 		bt_params.base_remote_ts = mach_bridge_compute_timestamp(bt_params.base_local_ts, &bt_params_snapshot);
431 		bt_params.rate = new_rate;
432 	}
433 	bt_params_add(&bt_params);
434 	commpage_set_remotetime_params(bt_params.rate, bt_params.base_local_ts, bt_params.base_remote_ts);
435 	KDBG(MACHDBG_CODE(DBG_MACH_CLOCK, MACH_BRIDGE_TS_PARAMS), bt_params.base_local_ts,
436 	    bt_params.base_remote_ts, *(uint64_t *)((void *)&bt_params.rate));
437 
438 skip_reset:
439 	lck_spin_unlock(&bt_ts_conversion_lock);
440 
441 	s = splsched();
442 	lck_spin_lock(&bt_spin_lock);
443 	/* Check if a new timestamp pair was received */
444 	if (received_local_timestamp != curr_local_abs) {
445 		recalculate_count++;
446 		goto recalculate;
447 	}
448 block:
449 	assert_wait((event_t)bt_params_hist, THREAD_UNINT);
450 	lck_spin_unlock(&bt_spin_lock);
451 	splx(s);
452 	thread_block((thread_continue_t)bt_calibration_thread);
453 }
454 
455 void
bt_calibration_thread_start(void)456 bt_calibration_thread_start(void)
457 {
458 	thread_t thread;
459 	kern_return_t result = kernel_thread_start_priority((thread_continue_t)bt_calibration_thread,
460 	    NULL, BASEPRI_KERNEL, &thread);
461 	if (result != KERN_SUCCESS) {
462 		panic("mach_bridge_add_timestamp: thread_timestamp_calibration");
463 	}
464 	thread_deallocate(thread);
465 }
466 
467 #endif /* CONFIG_MACH_BRIDGE_RECV_TIME */
468 
469 /**
470  * mach_bridge_remote_time
471  *
472  * This function is used to predict the remote CPU's clock time, given
473  * the local time.
474  *
475  * If local_timestamp = 0, then the remote_timestamp is calculated
476  * corresponding to the current mach_absolute_time.
477  *
478  * If XNU_TARGET_OS_BRIDGE is defined, then monotonicity of
479  * predicted time is guaranteed only for recent local_timestamp values
480  * lesser than the current mach_absolute_time upto 1 second.
481  *
482  * If CONFIG_MACH_BRIDGE_SEND_TIME is true, then the function is compiled
483  * for the remote CPU. If CONFIG_MACH_BRIDGE_RECV_TIME is true, then the
484  * the function is compiled for the local CPU. Both config options cannot
485  * be true simultaneously.
486  */
487 uint64_t
mach_bridge_remote_time(uint64_t local_timestamp)488 mach_bridge_remote_time(uint64_t local_timestamp)
489 {
490 #if defined(CONFIG_MACH_BRIDGE_SEND_TIME)
491 #if !defined(CONFIG_MACH_BRIDGE_RECV_TIME)
492 	/* only send side of the bridge is defined: no translation needed */
493 	if (!local_timestamp) {
494 		return mach_absolute_time();
495 	}
496 	return 0;
497 #else
498 #error "You cannot define both sides of the bridge!"
499 #endif /* !defined(CONFIG_MACH_BRIDGE_RECV_TIME) */
500 #else
501 #if !defined(CONFIG_MACH_BRIDGE_RECV_TIME)
502 	/* neither the send or receive side of the bridge is defined: echo the input */
503 	return local_timestamp;
504 #else
505 	if (!os_atomic_load(&bt_init_flag, acquire)) {
506 		return 0;
507 	}
508 
509 	uint64_t remote_timestamp = 0;
510 
511 	lck_spin_lock(&bt_ts_conversion_lock);
512 	uint64_t now = mach_absolute_time();
513 	if (!local_timestamp) {
514 		local_timestamp = now;
515 	}
516 #if defined(XNU_TARGET_OS_BRIDGE)
517 	uint64_t local_timestamp_ns = 0;
518 	if (local_timestamp < now) {
519 		absolutetime_to_nanoseconds(local_timestamp, &local_timestamp_ns);
520 		struct bt_params *params = bt_params_find(local_timestamp_ns);
521 		remote_timestamp = mach_bridge_compute_timestamp(local_timestamp_ns, params);
522 	}
523 #else
524 	struct bt_params params = bt_params_get_latest_locked();
525 	remote_timestamp = mach_bridge_compute_timestamp(local_timestamp, &params);
526 #endif /* defined(XNU_TARGET_OS_BRIDGE) */
527 	lck_spin_unlock(&bt_ts_conversion_lock);
528 	KDBG(MACHDBG_CODE(DBG_MACH_CLOCK, MACH_BRIDGE_REMOTE_TIME), local_timestamp, remote_timestamp, now);
529 
530 	return remote_timestamp;
531 #endif /* !defined(CONFIG_MACH_BRIDGE_RECV_TIME) */
532 #endif /* defined(CONFIG_MACH_BRIDGE_SEND_TIME) */
533 }
534