1 | /* |
2 | * Copyright (c) 2000-2020 Apple Inc. All rights reserved. |
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 | |
13 | #include <sys/types.h> |
14 | #include <mach/machine.h> |
15 | #include <kern/cpu_number.h> |
16 | #include <libkern/libkern.h> |
17 | #include <machine/exec.h> |
18 | #include <pexpert/arm64/board_config.h> |
19 | |
20 | #if __arm64__ |
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 | } |
39 | |
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 | return 0; |
50 | } |
51 | #endif /* XNU_TARGET_OS_IOS */ |
52 | |
53 | /* The current ABI version is preferred over arm64 */ |
54 | if (CPU_SUBTYPE_ARM64_PTR_AUTH_VERSION(execfeatures) == |
55 | CPU_SUBTYPE_ARM64_PTR_AUTH_CURRENT_VERSION) { |
56 | return 12; |
57 | } |
58 | |
59 | /* Future ABIs are allowed, but exec_mach_imgact will treat it like an arm64 slice */ |
60 | return 11; |
61 | } |
62 | #endif /* __arm64__ */ |
63 | |
64 | /********************************************************************** |
65 | * Routine: grade_binary() |
66 | * |
67 | * Function: Return a relative preference for exectypes and |
68 | * execsubtypes in fat executable files. The higher the |
69 | * grade, the higher the preference. A grade of 0 means |
70 | * not acceptable. |
71 | **********************************************************************/ |
72 | int |
73 | grade_binary(cpu_type_t exectype, cpu_subtype_t execsubtype, cpu_subtype_t execfeatures __unused, bool allow_simulator_binary __unused) |
74 | { |
75 | #if __arm64__ |
76 | cpu_subtype_t hostsubtype = |
77 | (exectype & CPU_ARCH_ABI64) ? cpu_subtype() : cpu_subtype32(); |
78 | #else |
79 | cpu_subtype_t hostsubtype = cpu_subtype(); |
80 | #endif /* __arm64__ */ |
81 | |
82 | switch (exectype) { |
83 | #if __arm64__ |
84 | case CPU_TYPE_ARM64: |
85 | switch (hostsubtype) { |
86 | case CPU_SUBTYPE_ARM64_V8: |
87 | switch (execsubtype) { |
88 | case CPU_SUBTYPE_ARM64_V8: |
89 | return 10; |
90 | case CPU_SUBTYPE_ARM64_ALL: |
91 | return 9; |
92 | } |
93 | break; |
94 | |
95 | case CPU_SUBTYPE_ARM64E: |
96 | switch (execsubtype) { |
97 | case CPU_SUBTYPE_ARM64E: |
98 | return grade_arm64e_binary(execfeatures); |
99 | case CPU_SUBTYPE_ARM64_V8: |
100 | return 10; |
101 | case CPU_SUBTYPE_ARM64_ALL: |
102 | return 9; |
103 | } |
104 | } /* switch (hostsubtype) */ |
105 | break; |
106 | |
107 | #else /* __arm64__ */ |
108 | |
109 | case CPU_TYPE_ARM: |
110 | switch (hostsubtype) { |
111 | /* |
112 | * For 32-bit ARMv8, try the ARMv8 slice before falling back to Swift. |
113 | */ |
114 | case CPU_SUBTYPE_ARM_V8: |
115 | switch (execsubtype) { |
116 | case CPU_SUBTYPE_ARM_V8: |
117 | return 7; |
118 | } |
119 | goto v7s; |
120 | |
121 | /* |
122 | * For Swift and later, we prefer to run a swift slice, but fall back |
123 | * to v7 as Cortex A9 errata should not apply |
124 | */ |
125 | v7s: |
126 | case CPU_SUBTYPE_ARM_V7S: |
127 | switch (execsubtype) { |
128 | case CPU_SUBTYPE_ARM_V7S: |
129 | return 6; |
130 | } |
131 | goto v7; |
132 | |
133 | /* |
134 | * For Cortex A7, accept v7k only due to differing ABI |
135 | */ |
136 | case CPU_SUBTYPE_ARM_V7K: |
137 | switch (execsubtype) { |
138 | case CPU_SUBTYPE_ARM_V7K: |
139 | return 6; |
140 | } |
141 | break; |
142 | |
143 | /* |
144 | * For Cortex A9, we prefer the A9 slice, but will run v7 albeit |
145 | * under the risk of hitting the NEON load/store errata |
146 | */ |
147 | case CPU_SUBTYPE_ARM_V7F: |
148 | switch (execsubtype) { |
149 | case CPU_SUBTYPE_ARM_V7F: |
150 | return 6; |
151 | } |
152 | goto v7; |
153 | |
154 | v7: |
155 | case CPU_SUBTYPE_ARM_V7: |
156 | switch (execsubtype) { |
157 | case CPU_SUBTYPE_ARM_V7: |
158 | return 5; |
159 | } |
160 | // fall through... |
161 | |
162 | case CPU_SUBTYPE_ARM_V6: |
163 | switch (execsubtype) { |
164 | case CPU_SUBTYPE_ARM_V6: |
165 | return 4; |
166 | } |
167 | // fall through... |
168 | |
169 | case CPU_SUBTYPE_ARM_V5TEJ: |
170 | switch (execsubtype) { |
171 | case CPU_SUBTYPE_ARM_V5TEJ: |
172 | return 3; |
173 | } |
174 | // fall through |
175 | |
176 | case CPU_SUBTYPE_ARM_V4T: |
177 | switch (execsubtype) { |
178 | case CPU_SUBTYPE_ARM_V4T: |
179 | return 2; |
180 | case CPU_SUBTYPE_ARM_ALL: |
181 | return 1; |
182 | } |
183 | break; |
184 | |
185 | case CPU_SUBTYPE_ARM_XSCALE: |
186 | switch (execsubtype) { |
187 | case CPU_SUBTYPE_ARM_XSCALE: |
188 | return 4; |
189 | case CPU_SUBTYPE_ARM_V5TEJ: |
190 | return 3; |
191 | case CPU_SUBTYPE_ARM_V4T: |
192 | return 2; |
193 | case CPU_SUBTYPE_ARM_ALL: |
194 | return 1; |
195 | } |
196 | break; |
197 | } |
198 | #endif /* __arm64__ */ |
199 | } |
200 | |
201 | return 0; |
202 | } |
203 | |