1 | /* |
2 | * Copyright (c) 2000-2007 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 <machine/exec.h> |
17 | #include <pexpert/arm64/board_config.h> |
18 | |
19 | #if __arm64__ |
20 | extern int bootarg_no64exec; /* bsd_init.c */ |
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 | #endif /* __arm64__*/ |
40 | |
41 | /********************************************************************** |
42 | * Routine: grade_binary() |
43 | * |
44 | * Function: Return a relative preference for exectypes and |
45 | * execsubtypes in fat executable files. The higher the |
46 | * grade, the higher the preference. A grade of 0 means |
47 | * not acceptable. |
48 | **********************************************************************/ |
49 | int |
50 | grade_binary(cpu_type_t exectype, cpu_subtype_t execsubtype) |
51 | { |
52 | #if __arm64__ |
53 | cpu_subtype_t hostsubtype = |
54 | (exectype & CPU_ARCH_ABI64) ? cpu_subtype() : cpu_subtype32(); |
55 | #else |
56 | cpu_subtype_t hostsubtype = cpu_subtype(); |
57 | #endif /* __arm64__ */ |
58 | |
59 | switch (exectype) { |
60 | #if __arm64__ |
61 | case CPU_TYPE_ARM64: |
62 | if (bootarg_no64exec) return 0; |
63 | |
64 | switch (hostsubtype) { |
65 | case CPU_SUBTYPE_ARM64_V8: |
66 | switch (execsubtype) { |
67 | case CPU_SUBTYPE_ARM64_V8: |
68 | return 10; |
69 | case CPU_SUBTYPE_ARM64_ALL: |
70 | return 9; |
71 | } |
72 | break; |
73 | |
74 | } /* switch (hostsubtype) */ |
75 | |
76 | #else /* __arm64__ */ |
77 | |
78 | case CPU_TYPE_ARM: |
79 | switch (hostsubtype) { |
80 | /* |
81 | * For 32-bit ARMv8, try the ARMv8 slice before falling back to Swift. |
82 | */ |
83 | case CPU_SUBTYPE_ARM_V8: |
84 | switch (execsubtype) { |
85 | case CPU_SUBTYPE_ARM_V8: |
86 | return 7; |
87 | } |
88 | goto v7s; |
89 | |
90 | /* |
91 | * For Swift and later, we prefer to run a swift slice, but fall back |
92 | * to v7 as Cortex A9 errata should not apply |
93 | */ |
94 | v7s: |
95 | case CPU_SUBTYPE_ARM_V7S: |
96 | switch (execsubtype) { |
97 | case CPU_SUBTYPE_ARM_V7S: |
98 | return 6; |
99 | } |
100 | goto v7; |
101 | |
102 | /* |
103 | * For Cortex A7, accept v7k only due to differing ABI |
104 | */ |
105 | case CPU_SUBTYPE_ARM_V7K: |
106 | switch (execsubtype) { |
107 | case CPU_SUBTYPE_ARM_V7K: |
108 | return 6; |
109 | } |
110 | break; |
111 | |
112 | /* |
113 | * For Cortex A9, we prefer the A9 slice, but will run v7 albeit |
114 | * under the risk of hitting the NEON load/store errata |
115 | */ |
116 | case CPU_SUBTYPE_ARM_V7F: |
117 | switch (execsubtype) { |
118 | case CPU_SUBTYPE_ARM_V7F: |
119 | return 6; |
120 | } |
121 | goto v7; |
122 | |
123 | v7: |
124 | case CPU_SUBTYPE_ARM_V7: |
125 | switch (execsubtype) { |
126 | case CPU_SUBTYPE_ARM_V7: |
127 | return 5; |
128 | } |
129 | // fall through... |
130 | |
131 | case CPU_SUBTYPE_ARM_V6: |
132 | switch (execsubtype) { |
133 | case CPU_SUBTYPE_ARM_V6: |
134 | return 4; |
135 | } |
136 | // fall through... |
137 | |
138 | case CPU_SUBTYPE_ARM_V5TEJ: |
139 | switch (execsubtype) { |
140 | case CPU_SUBTYPE_ARM_V5TEJ: |
141 | return 3; |
142 | } |
143 | // fall through |
144 | |
145 | case CPU_SUBTYPE_ARM_V4T: |
146 | switch (execsubtype) { |
147 | case CPU_SUBTYPE_ARM_V4T: |
148 | return 2; |
149 | case CPU_SUBTYPE_ARM_ALL: |
150 | return 1; |
151 | } |
152 | break; |
153 | |
154 | case CPU_SUBTYPE_ARM_XSCALE: |
155 | switch (execsubtype) { |
156 | case CPU_SUBTYPE_ARM_XSCALE: |
157 | return 4; |
158 | case CPU_SUBTYPE_ARM_V5TEJ: |
159 | return 3; |
160 | case CPU_SUBTYPE_ARM_V4T: |
161 | return 2; |
162 | case CPU_SUBTYPE_ARM_ALL: |
163 | return 1; |
164 | } |
165 | break; |
166 | } |
167 | #endif /* __arm64__ */ |
168 | } |
169 | |
170 | return 0; |
171 | } |
172 | |
173 | boolean_t |
174 | pie_required(cpu_type_t exectype, cpu_subtype_t execsubtype) |
175 | { |
176 | switch (exectype) { |
177 | #if __arm64__ |
178 | case CPU_TYPE_ARM64: |
179 | return TRUE; |
180 | #endif /* __arm64__ */ |
181 | |
182 | case CPU_TYPE_ARM: |
183 | switch (execsubtype) { |
184 | case CPU_SUBTYPE_ARM_V7K: |
185 | return TRUE; |
186 | } |
187 | break; |
188 | } |
189 | return FALSE; |
190 | } |
191 | |