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__
20extern int bootarg_no64exec; /* bsd_init.c */
21static 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 */
29static cpu_subtype_t
30cpu_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 **********************************************************************/
49int
50grade_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 */
94v7s:
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
123v7:
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
173boolean_t
174pie_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