]>
Commit | Line | Data |
---|---|---|
5ba3f43e | 1 | /* |
f427ee49 | 2 | * Copyright (c) 2000-2020 Apple Inc. All rights reserved. |
5ba3f43e A |
3 | */ |
4 | /* | |
5 | * Copyright (C) 1990, NeXT, Inc. | |
6 | * | |
7 | * File: next/kern_machdep.c | |
8 | * Author: John Seamons | |
9 | * | |
10 | * Machine-specific kernel routines. | |
11 | */ | |
12 | ||
0a7de745 A |
13 | #include <sys/types.h> |
14 | #include <mach/machine.h> | |
15 | #include <kern/cpu_number.h> | |
f427ee49 | 16 | #include <libkern/libkern.h> |
0a7de745 A |
17 | #include <machine/exec.h> |
18 | #include <pexpert/arm64/board_config.h> | |
5ba3f43e A |
19 | |
20 | #if __arm64__ | |
5ba3f43e A |
21 | static cpu_subtype_t cpu_subtype32(void); |
22 | #endif /* __arm64__ */ | |
23 | ||
24 | #if __arm64__ | |
25 | /* | |
26 | * When an arm64 CPU is executing an arm32 binary, we need to map from the | |
27 | * host's 64-bit subtype to the appropriate 32-bit subtype. | |
28 | */ | |
29 | static cpu_subtype_t | |
30 | cpu_subtype32() | |
31 | { | |
32 | switch (cpu_subtype()) { | |
33 | case CPU_SUBTYPE_ARM64_V8: | |
34 | return CPU_SUBTYPE_ARM_V8; | |
35 | default: | |
36 | return 0; | |
37 | } | |
38 | } | |
f427ee49 | 39 | |
2a1bd2d3 A |
40 | static int |
41 | grade_arm64e_binary(cpu_subtype_t execfeatures) | |
42 | { | |
43 | #if XNU_TARGET_OS_IOS | |
44 | /* | |
45 | * iOS 13 toolchains produced unversioned arm64e slices which are not | |
46 | * ABI compatible with this release. | |
47 | */ | |
48 | if ((execfeatures & CPU_SUBTYPE_PTRAUTH_ABI) == 0) { | |
49 | #if DEBUG || DEVELOPMENT | |
50 | printf("%s: arm64e prerelease ABI cannot be used with this kernel\n", __func__); | |
51 | #endif /* DEBUG || DEVELOPMENT */ | |
52 | return 0; | |
53 | } | |
54 | #endif /* XNU_TARGET_OS_IOS */ | |
55 | ||
56 | /* The current ABI version is preferred over arm64 */ | |
57 | if (CPU_SUBTYPE_ARM64_PTR_AUTH_VERSION(execfeatures) == | |
58 | CPU_SUBTYPE_ARM64_PTR_AUTH_CURRENT_VERSION) { | |
59 | return 12; | |
60 | } | |
61 | ||
62 | /* Future ABIs are allowed, but exec_mach_imgact will treat it like an arm64 slice */ | |
63 | return 11; | |
64 | } | |
f427ee49 | 65 | #endif /* __arm64__ */ |
5ba3f43e A |
66 | |
67 | /********************************************************************** | |
0a7de745 A |
68 | * Routine: grade_binary() |
69 | * | |
70 | * Function: Return a relative preference for exectypes and | |
71 | * execsubtypes in fat executable files. The higher the | |
72 | * grade, the higher the preference. A grade of 0 means | |
73 | * not acceptable. | |
74 | **********************************************************************/ | |
5ba3f43e | 75 | int |
f427ee49 | 76 | grade_binary(cpu_type_t exectype, cpu_subtype_t execsubtype, cpu_subtype_t execfeatures __unused, bool allow_simulator_binary __unused) |
5ba3f43e A |
77 | { |
78 | #if __arm64__ | |
d9a64523 | 79 | cpu_subtype_t hostsubtype = |
0a7de745 | 80 | (exectype & CPU_ARCH_ABI64) ? cpu_subtype() : cpu_subtype32(); |
5ba3f43e A |
81 | #else |
82 | cpu_subtype_t hostsubtype = cpu_subtype(); | |
83 | #endif /* __arm64__ */ | |
84 | ||
85 | switch (exectype) { | |
86 | #if __arm64__ | |
87 | case CPU_TYPE_ARM64: | |
5ba3f43e A |
88 | switch (hostsubtype) { |
89 | case CPU_SUBTYPE_ARM64_V8: | |
90 | switch (execsubtype) { | |
91 | case CPU_SUBTYPE_ARM64_V8: | |
d9a64523 | 92 | return 10; |
5ba3f43e | 93 | case CPU_SUBTYPE_ARM64_ALL: |
d9a64523 | 94 | return 9; |
5ba3f43e A |
95 | } |
96 | break; | |
97 | ||
2a1bd2d3 A |
98 | case CPU_SUBTYPE_ARM64E: |
99 | switch (execsubtype) { | |
100 | case CPU_SUBTYPE_ARM64E: | |
101 | return grade_arm64e_binary(execfeatures); | |
102 | case CPU_SUBTYPE_ARM64_V8: | |
103 | return 10; | |
104 | case CPU_SUBTYPE_ARM64_ALL: | |
105 | return 9; | |
106 | } | |
d9a64523 | 107 | } /* switch (hostsubtype) */ |
f427ee49 | 108 | break; |
5ba3f43e | 109 | |
5ba3f43e A |
110 | #else /* __arm64__ */ |
111 | ||
112 | case CPU_TYPE_ARM: | |
113 | switch (hostsubtype) { | |
114 | /* | |
115 | * For 32-bit ARMv8, try the ARMv8 slice before falling back to Swift. | |
116 | */ | |
117 | case CPU_SUBTYPE_ARM_V8: | |
118 | switch (execsubtype) { | |
119 | case CPU_SUBTYPE_ARM_V8: | |
120 | return 7; | |
121 | } | |
122 | goto v7s; | |
123 | ||
0a7de745 A |
124 | /* |
125 | * For Swift and later, we prefer to run a swift slice, but fall back | |
126 | * to v7 as Cortex A9 errata should not apply | |
127 | */ | |
5ba3f43e A |
128 | v7s: |
129 | case CPU_SUBTYPE_ARM_V7S: | |
130 | switch (execsubtype) { | |
131 | case CPU_SUBTYPE_ARM_V7S: | |
132 | return 6; | |
133 | } | |
134 | goto v7; | |
135 | ||
136 | /* | |
137 | * For Cortex A7, accept v7k only due to differing ABI | |
138 | */ | |
139 | case CPU_SUBTYPE_ARM_V7K: | |
140 | switch (execsubtype) { | |
141 | case CPU_SUBTYPE_ARM_V7K: | |
142 | return 6; | |
143 | } | |
0a7de745 | 144 | break; |
5ba3f43e A |
145 | |
146 | /* | |
147 | * For Cortex A9, we prefer the A9 slice, but will run v7 albeit | |
148 | * under the risk of hitting the NEON load/store errata | |
149 | */ | |
150 | case CPU_SUBTYPE_ARM_V7F: | |
151 | switch (execsubtype) { | |
152 | case CPU_SUBTYPE_ARM_V7F: | |
153 | return 6; | |
154 | } | |
155 | goto v7; | |
156 | ||
157 | v7: | |
158 | case CPU_SUBTYPE_ARM_V7: | |
159 | switch (execsubtype) { | |
160 | case CPU_SUBTYPE_ARM_V7: | |
161 | return 5; | |
162 | } | |
0a7de745 | 163 | // fall through... |
5ba3f43e A |
164 | |
165 | case CPU_SUBTYPE_ARM_V6: | |
166 | switch (execsubtype) { | |
167 | case CPU_SUBTYPE_ARM_V6: | |
168 | return 4; | |
169 | } | |
0a7de745 | 170 | // fall through... |
5ba3f43e A |
171 | |
172 | case CPU_SUBTYPE_ARM_V5TEJ: | |
173 | switch (execsubtype) { | |
174 | case CPU_SUBTYPE_ARM_V5TEJ: | |
175 | return 3; | |
176 | } | |
0a7de745 | 177 | // fall through |
5ba3f43e A |
178 | |
179 | case CPU_SUBTYPE_ARM_V4T: | |
180 | switch (execsubtype) { | |
181 | case CPU_SUBTYPE_ARM_V4T: | |
182 | return 2; | |
183 | case CPU_SUBTYPE_ARM_ALL: | |
184 | return 1; | |
185 | } | |
186 | break; | |
187 | ||
188 | case CPU_SUBTYPE_ARM_XSCALE: | |
189 | switch (execsubtype) { | |
190 | case CPU_SUBTYPE_ARM_XSCALE: | |
191 | return 4; | |
192 | case CPU_SUBTYPE_ARM_V5TEJ: | |
193 | return 3; | |
194 | case CPU_SUBTYPE_ARM_V4T: | |
195 | return 2; | |
196 | case CPU_SUBTYPE_ARM_ALL: | |
197 | return 1; | |
198 | } | |
199 | break; | |
200 | } | |
201 | #endif /* __arm64__ */ | |
202 | } | |
203 | ||
204 | return 0; | |
205 | } |