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