]>
Commit | Line | Data |
---|---|---|
d26ffc64 A |
1 | /* |
2 | * Copyright (c) 2018 Apple Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_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. Please obtain a copy of the License at | |
10 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
11 | * file. | |
12 | * | |
13 | * The Original Code and all software distributed under the License are | |
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
18 | * Please see the License for the specific language governing rights and | |
19 | * limitations under the License. | |
20 | * | |
21 | * @APPLE_LICENSE_HEADER_END@ | |
22 | */ | |
23 | #include <sys/types.h> | |
24 | #include <machine/cpu_capabilities.h> | |
25 | #include <kern/remote_time.h> | |
26 | #include <mach/mach_time.h> | |
27 | #include "strings.h" | |
28 | #include <TargetConditionals.h> | |
29 | ||
30 | #define BT_RESET_SENTINEL_TS (~3ULL) /* from machine/machine_remote_time.h */ | |
31 | ||
32 | extern uint64_t __mach_bridge_remote_time(uint64_t local_time); | |
33 | ||
34 | #if TARGET_OS_BRIDGE && defined(__arm64__) | |
35 | static uint64_t | |
36 | absolutetime_to_nanoseconds(uint64_t abs_time) | |
37 | { | |
38 | mach_timebase_info_data_t info; | |
39 | mach_timebase_info(&info); | |
40 | uint64_t time_in_ns = (uint64_t)(((double)info.numer / (double)info.denom) * abs_time); | |
41 | ||
42 | return time_in_ns; | |
43 | } | |
44 | ||
45 | uint64_t | |
46 | mach_bridge_remote_time(__unused uint64_t local_time) | |
47 | { | |
48 | uint64_t remote_time = 0; | |
49 | uint64_t local_time_ns = 0; | |
50 | uint64_t now = 0; | |
51 | struct bt_params params = {}; | |
52 | ||
53 | volatile struct bt_params *commpage_bt_params_p = (struct bt_params *)_COMM_PAGE_REMOTETIME_PARAMS; | |
54 | volatile uint64_t *base_local_ts_p = &commpage_bt_params_p->base_local_ts; | |
55 | volatile uint64_t *base_remote_ts_p = &commpage_bt_params_p->base_remote_ts; | |
56 | volatile double *rate_p = &commpage_bt_params_p->rate; | |
57 | ||
58 | do { | |
59 | params.base_local_ts = *base_local_ts_p; | |
60 | if (*base_local_ts_p == BT_RESET_SENTINEL_TS) { | |
61 | return 0; | |
62 | } | |
63 | /* | |
64 | * This call contains an instruction barrier that ensures the second read of | |
65 | * base_local_ts is not speculated above the first read of base_local_ts. | |
66 | */ | |
67 | now = mach_absolute_time(); | |
68 | params.base_remote_ts = *base_remote_ts_p; | |
69 | params.rate = *rate_p; | |
70 | /* | |
71 | * This barrier prevents the second read of base_local_ts from being reordered | |
72 | * w.r.t the reads of other values in bt_params. | |
73 | */ | |
0a7de745 A |
74 | __asm__ volatile ("dmb ishld" ::: "memory"); |
75 | } while (params.base_local_ts && (params.base_local_ts != commpage_bt_params_p->base_local_ts)); | |
d26ffc64 A |
76 | |
77 | if (!local_time) { | |
78 | local_time = now; | |
79 | } | |
80 | local_time_ns = absolutetime_to_nanoseconds(local_time); | |
81 | if (local_time_ns < params.base_local_ts) { | |
82 | remote_time = __mach_bridge_remote_time(local_time); | |
83 | } else { | |
84 | remote_time = mach_bridge_compute_timestamp(local_time_ns, ¶ms); | |
85 | } | |
86 | return remote_time; | |
87 | } | |
88 | #endif /* TARGET_OS_BRIDGE && defined(__arm64__) */ |