--- /dev/null
+/*
+ * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
+ */
+/*
+ * Copyright (C) 1990, NeXT, Inc.
+ *
+ * File: next/kern_machdep.c
+ * Author: John Seamons
+ *
+ * Machine-specific kernel routines.
+ */
+
+#include <sys/types.h>
+#include <mach/machine.h>
+#include <kern/cpu_number.h>
+#include <machine/exec.h>
+
+#if __arm64__
+extern int bootarg_no64exec; /* bsd_init.c */
+static cpu_subtype_t cpu_subtype32(void);
+#endif /* __arm64__ */
+
+#if __arm64__
+/*
+ * When an arm64 CPU is executing an arm32 binary, we need to map from the
+ * host's 64-bit subtype to the appropriate 32-bit subtype.
+ */
+static cpu_subtype_t
+cpu_subtype32()
+{
+ switch (cpu_subtype()) {
+ case CPU_SUBTYPE_ARM64_V8:
+ return CPU_SUBTYPE_ARM_V8;
+ default:
+ return 0;
+ }
+}
+#endif /* __arm64__*/
+
+/**********************************************************************
+ * Routine: grade_binary()
+ *
+ * Function: Return a relative preference for exectypes and
+ * execsubtypes in fat executable files. The higher the
+ * grade, the higher the preference. A grade of 0 means
+ * not acceptable.
+ **********************************************************************/
+int
+grade_binary(cpu_type_t exectype, cpu_subtype_t execsubtype)
+{
+#if __arm64__
+ cpu_subtype_t hostsubtype = (exectype & CPU_ARCH_ABI64) ? cpu_subtype() : cpu_subtype32();
+#else
+ cpu_subtype_t hostsubtype = cpu_subtype();
+#endif /* __arm64__ */
+
+ switch (exectype) {
+#if __arm64__
+ case CPU_TYPE_ARM64:
+ if (bootarg_no64exec) return 0;
+
+ switch (hostsubtype) {
+ case CPU_SUBTYPE_ARM64_V8:
+ switch (execsubtype) {
+ case CPU_SUBTYPE_ARM64_V8:
+ return 9;
+ case CPU_SUBTYPE_ARM64_ALL:
+ return 8;
+ }
+ break;
+
+
+ break;
+#else /* __arm64__ */
+
+ case CPU_TYPE_ARM:
+ switch (hostsubtype) {
+ /*
+ * For 32-bit ARMv8, try the ARMv8 slice before falling back to Swift.
+ */
+ case CPU_SUBTYPE_ARM_V8:
+ switch (execsubtype) {
+ case CPU_SUBTYPE_ARM_V8:
+ return 7;
+ }
+ goto v7s;
+
+ /*
+ * For Swift and later, we prefer to run a swift slice, but fall back
+ * to v7 as Cortex A9 errata should not apply
+ */
+v7s:
+ case CPU_SUBTYPE_ARM_V7S:
+ switch (execsubtype) {
+ case CPU_SUBTYPE_ARM_V7S:
+ return 6;
+ }
+ goto v7;
+
+ /*
+ * For Cortex A7, accept v7k only due to differing ABI
+ */
+ case CPU_SUBTYPE_ARM_V7K:
+ switch (execsubtype) {
+ case CPU_SUBTYPE_ARM_V7K:
+ return 6;
+ }
+ break;
+
+ /*
+ * For Cortex A9, we prefer the A9 slice, but will run v7 albeit
+ * under the risk of hitting the NEON load/store errata
+ */
+ case CPU_SUBTYPE_ARM_V7F:
+ switch (execsubtype) {
+ case CPU_SUBTYPE_ARM_V7F:
+ return 6;
+ }
+ goto v7;
+
+v7:
+ case CPU_SUBTYPE_ARM_V7:
+ switch (execsubtype) {
+ case CPU_SUBTYPE_ARM_V7:
+ return 5;
+ }
+ // fall through...
+
+ case CPU_SUBTYPE_ARM_V6:
+ switch (execsubtype) {
+ case CPU_SUBTYPE_ARM_V6:
+ return 4;
+ }
+ // fall through...
+
+ case CPU_SUBTYPE_ARM_V5TEJ:
+ switch (execsubtype) {
+ case CPU_SUBTYPE_ARM_V5TEJ:
+ return 3;
+ }
+ // fall through
+
+ case CPU_SUBTYPE_ARM_V4T:
+ switch (execsubtype) {
+ case CPU_SUBTYPE_ARM_V4T:
+ return 2;
+ case CPU_SUBTYPE_ARM_ALL:
+ return 1;
+ }
+ break;
+
+ case CPU_SUBTYPE_ARM_XSCALE:
+ switch (execsubtype) {
+ case CPU_SUBTYPE_ARM_XSCALE:
+ return 4;
+ case CPU_SUBTYPE_ARM_V5TEJ:
+ return 3;
+ case CPU_SUBTYPE_ARM_V4T:
+ return 2;
+ case CPU_SUBTYPE_ARM_ALL:
+ return 1;
+ }
+ break;
+ }
+#endif /* __arm64__ */
+ }
+
+ return 0;
+}
+
+boolean_t
+pie_required(cpu_type_t exectype, cpu_subtype_t execsubtype)
+{
+ switch (exectype) {
+#if __arm64__
+ case CPU_TYPE_ARM64:
+ return TRUE;
+#endif /* __arm64__ */
+
+ case CPU_TYPE_ARM:
+ switch (execsubtype) {
+ case CPU_SUBTYPE_ARM_V7K:
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}