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
cpu_subtype32()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
grade_arm64e_binary(cpu_subtype_t execfeatures)41 grade_arm64e_binary(cpu_subtype_t execfeatures)
42 {
43 #if XNU_TARGET_OS_IOS || XNU_TARGET_OS_XR
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 || XNU_TARGET_OS_XR */
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
grade_binary(cpu_type_t exectype,cpu_subtype_t execsubtype,cpu_subtype_t execfeatures __unused,bool allow_simulator_binary __unused)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