2 * mono-hwcap-arm.c: ARM hardware feature detection
5 * Alex Rønne Petersen (alexrp@xamarin.com)
6 * Elijah Taylor (elijahtaylor@google.com)
7 * Miguel de Icaza (miguel@xamarin.com)
8 * Neale Ferguson (Neale.Ferguson@SoftwareAG-usa.com)
9 * Paolo Molaro (lupus@xamarin.com)
10 * Rodrigo Kumpera (kumpera@gmail.com)
11 * Sebastien Pouliot (sebastien@xamarin.com)
12 * Zoltan Varga (vargaz@xamarin.com)
14 * Copyright 2003 Ximian, Inc.
15 * Copyright 2003-2011 Novell, Inc
16 * Copyright 2006 Broadcom
17 * Copyright 2007-2008 Andreas Faerber
18 * Copyright 2011-2013 Xamarin Inc
19 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
22 #include "mono/utils/mono-hwcap.h"
24 #if defined(HAVE_SYS_AUXV_H) && !defined(PLATFORM_ANDROID)
26 #elif defined(__APPLE__)
27 #include <mach/machine.h>
28 #include <sys/sysctl.h>
29 #include <sys/types.h>
31 #if defined (HAVE_SYS_UTSNAME_H)
32 #include <sys/utsname.h>
38 mono_hwcap_arch_init (void)
40 #if defined(HAVE_SYS_AUXV_H) && !defined(PLATFORM_ANDROID)
42 unsigned long platform
;
44 if ((hwcap
= getauxval(AT_HWCAP
))) {
46 if (hwcap
& 0x00000004)
47 mono_hwcap_arm_has_thumb
= TRUE
;
50 if (hwcap
& 0x00000040)
51 mono_hwcap_arm_has_vfp
= TRUE
;
54 if (hwcap
& 0x00002000)
55 mono_hwcap_arm_has_vfp3
= TRUE
;
57 /* HWCAP_ARM_VFPv3D16 */
58 if (hwcap
& 0x00004000)
59 mono_hwcap_arm_has_vfp3_d16
= TRUE
;
61 /* TODO: Find a way to detect Thumb 2. */
64 if ((platform
= getauxval(AT_PLATFORM
))) {
65 const char *str
= (const char *) platform
;
68 mono_hwcap_arm_is_v5
= TRUE
;
71 mono_hwcap_arm_is_v6
= TRUE
;
74 mono_hwcap_arm_is_v7
= TRUE
;
76 /* TODO: Find a way to detect v7s. */
78 #elif defined(__APPLE__)
79 cpu_subtype_t sub_type
;
80 size_t length
= sizeof (sub_type
);
82 sysctlbyname ("hw.cpusubtype", &sub_type
, &length
, NULL
, 0);
84 if (sub_type
== CPU_SUBTYPE_ARM_V5TEJ
|| sub_type
== CPU_SUBTYPE_ARM_XSCALE
) {
85 mono_hwcap_arm_is_v5
= TRUE
;
86 } else if (sub_type
== CPU_SUBTYPE_ARM_V6
) {
87 mono_hwcap_arm_is_v5
= TRUE
;
88 mono_hwcap_arm_is_v6
= TRUE
;
89 } else if (sub_type
== CPU_SUBTYPE_ARM_V7
|| sub_type
== CPU_SUBTYPE_ARM_V7F
|| sub_type
== CPU_SUBTYPE_ARM_V7K
) {
90 mono_hwcap_arm_is_v5
= TRUE
;
91 mono_hwcap_arm_is_v6
= TRUE
;
92 mono_hwcap_arm_is_v7
= TRUE
;
95 /* TODO: Find a way to detect features like Thumb and VFP. */
97 /* We can't use the auxiliary vector on Android due to
98 * permissions, so fall back to /proc/cpuinfo. We also
99 * hit this path if the target doesn't have sys/auxv.h.
102 #if defined (HAVE_SYS_UTSNAME_H)
105 /* Only fails if `name` is invalid (it isn't). */
106 g_assert (!uname (&name
));
108 if (!strncmp (name
.machine
, "aarch64", 7) || !strncmp (name
.machine
, "armv8", 5)) {
110 * We're a 32-bit program running on an ARMv8 system.
111 * Whether the system is actually 32-bit or 64-bit
112 * doesn't matter to us. The important thing is that
113 * all 3 of ARMv8's execution states (A64, A32, T32)
114 * are guaranteed to have all of the features that
115 * we want to detect and use.
117 * We do this ARMv8 detection via uname () because
118 * in the early days of ARMv8 on Linux, the
119 * /proc/cpuinfo format was a disaster and there
120 * were multiple (merged into mainline) attempts at
121 * cleaning it up (read: breaking applications that
122 * tried to rely on it). So now multiple ARMv8
123 * systems in the wild have different /proc/cpuinfo
124 * output, some of which are downright useless.
126 * So, when it comes to detecting ARMv8 in a 32-bit
127 * program, it's better to just avoid /proc/cpuinfo
128 * entirely. Maybe in a decade or two, we won't
129 * have to worry about this mess that the Linux ARM
130 * maintainers created. One can hope.
133 mono_hwcap_arm_is_v5
= TRUE
;
134 mono_hwcap_arm_is_v6
= TRUE
;
135 mono_hwcap_arm_is_v7
= TRUE
;
137 mono_hwcap_arm_has_vfp
= TRUE
;
138 mono_hwcap_arm_has_vfp3
= TRUE
;
139 mono_hwcap_arm_has_vfp3_d16
= TRUE
;
141 mono_hwcap_arm_has_thumb
= TRUE
;
142 mono_hwcap_arm_has_thumb2
= TRUE
;
149 FILE *file
= fopen ("/proc/cpuinfo", "r");
152 while ((line
= fgets (buf
, 512, file
))) {
153 if (!strncmp (line
, "Processor", 9) ||
154 !strncmp (line
, "model name", 10)) {
155 char *ver
= strstr (line
, "(v");
159 mono_hwcap_arm_is_v5
= TRUE
;
162 mono_hwcap_arm_is_v6
= TRUE
;
165 mono_hwcap_arm_is_v7
= TRUE
;
167 /* TODO: Find a way to detect v7s. */
173 if (!strncmp (line
, "Features", 8)) {
174 if (strstr (line
, "thumb"))
175 mono_hwcap_arm_has_thumb
= TRUE
;
177 /* TODO: Find a way to detect Thumb 2. */
179 if (strstr (line
, "vfp"))
180 mono_hwcap_arm_has_vfp
= TRUE
;
182 if (strstr (line
, "vfpv3"))
183 mono_hwcap_arm_has_vfp3
= TRUE
;
185 if (strstr (line
, "vfpv3-d16"))
186 mono_hwcap_arm_has_vfp3_d16
= TRUE
;