xref: /xnu-8796.101.5/bsd/dev/arm/kern_machdep.c (revision aca3beaa3dfbd42498b42c5e5ce20a938e6554e5)
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
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
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