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