Merge pull request #4630 from BrzVlad/feature-valloc-limit
[mono-project.git] / mono / utils / mono-hwcap-arm.c
blob4ab9cd7b05ecb8898fe3738ac3e21cf940e13049
1 /**
2 * \file
3 * ARM hardware feature detection
5 * Authors:
6 * Alex Rønne Petersen (alexrp@xamarin.com)
7 * Elijah Taylor (elijahtaylor@google.com)
8 * Miguel de Icaza (miguel@xamarin.com)
9 * Neale Ferguson (Neale.Ferguson@SoftwareAG-usa.com)
10 * Paolo Molaro (lupus@xamarin.com)
11 * Rodrigo Kumpera (kumpera@gmail.com)
12 * Sebastien Pouliot (sebastien@xamarin.com)
13 * Zoltan Varga (vargaz@xamarin.com)
15 * Copyright 2003 Ximian, Inc.
16 * Copyright 2003-2011 Novell, Inc
17 * Copyright 2006 Broadcom
18 * Copyright 2007-2008 Andreas Faerber
19 * Copyright 2011-2013 Xamarin Inc
20 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
23 #include "mono/utils/mono-hwcap.h"
25 #if defined(HAVE_SYS_AUXV_H) && !defined(PLATFORM_ANDROID)
26 #include <sys/auxv.h>
27 #elif defined(__APPLE__)
28 #include <mach/machine.h>
29 #include <sys/sysctl.h>
30 #include <sys/types.h>
31 #else
32 #if defined (HAVE_SYS_UTSNAME_H)
33 #include <sys/utsname.h>
34 #endif
35 #include <stdio.h>
36 #endif
38 void
39 mono_hwcap_arch_init (void)
41 #if defined(HAVE_SYS_AUXV_H) && !defined(PLATFORM_ANDROID)
42 unsigned long hwcap;
43 unsigned long platform;
45 if ((hwcap = getauxval(AT_HWCAP))) {
46 /* HWCAP_ARM_THUMB */
47 if (hwcap & 0x00000004)
48 mono_hwcap_arm_has_thumb = TRUE;
50 /* HWCAP_ARM_VFP */
51 if (hwcap & 0x00000040)
52 mono_hwcap_arm_has_vfp = TRUE;
54 /* HWCAP_ARM_VFPv3 */
55 if (hwcap & 0x00002000)
56 mono_hwcap_arm_has_vfp3 = TRUE;
58 /* HWCAP_ARM_VFPv3D16 */
59 if (hwcap & 0x00004000)
60 mono_hwcap_arm_has_vfp3_d16 = TRUE;
62 /* TODO: Find a way to detect Thumb 2. */
65 if ((platform = getauxval(AT_PLATFORM))) {
66 const char *str = (const char *) platform;
68 if (str [1] >= '5')
69 mono_hwcap_arm_is_v5 = TRUE;
71 if (str [1] >= '6')
72 mono_hwcap_arm_is_v6 = TRUE;
74 if (str [1] >= '7')
75 mono_hwcap_arm_is_v7 = TRUE;
77 /* TODO: Find a way to detect v7s. */
79 #elif defined(__APPLE__)
80 cpu_subtype_t sub_type;
81 size_t length = sizeof (sub_type);
83 sysctlbyname ("hw.cpusubtype", &sub_type, &length, NULL, 0);
85 if (sub_type == CPU_SUBTYPE_ARM_V5TEJ || sub_type == CPU_SUBTYPE_ARM_XSCALE) {
86 mono_hwcap_arm_is_v5 = TRUE;
87 } else if (sub_type == CPU_SUBTYPE_ARM_V6) {
88 mono_hwcap_arm_is_v5 = TRUE;
89 mono_hwcap_arm_is_v6 = TRUE;
90 } else if (sub_type == CPU_SUBTYPE_ARM_V7 || sub_type == CPU_SUBTYPE_ARM_V7F || sub_type == CPU_SUBTYPE_ARM_V7K) {
91 mono_hwcap_arm_is_v5 = TRUE;
92 mono_hwcap_arm_is_v6 = TRUE;
93 mono_hwcap_arm_is_v7 = TRUE;
96 /* TODO: Find a way to detect features like Thumb and VFP. */
97 #else
98 /* We can't use the auxiliary vector on Android due to
99 * permissions, so fall back to /proc/cpuinfo. We also
100 * hit this path if the target doesn't have sys/auxv.h.
103 #if defined (HAVE_SYS_UTSNAME_H)
104 struct utsname name;
106 /* Only fails if `name` is invalid (it isn't). */
107 g_assert (!uname (&name));
109 if (!strncmp (name.machine, "aarch64", 7) || !strncmp (name.machine, "armv8", 5)) {
111 * We're a 32-bit program running on an ARMv8 system.
112 * Whether the system is actually 32-bit or 64-bit
113 * doesn't matter to us. The important thing is that
114 * all 3 of ARMv8's execution states (A64, A32, T32)
115 * are guaranteed to have all of the features that
116 * we want to detect and use.
118 * We do this ARMv8 detection via uname () because
119 * in the early days of ARMv8 on Linux, the
120 * /proc/cpuinfo format was a disaster and there
121 * were multiple (merged into mainline) attempts at
122 * cleaning it up (read: breaking applications that
123 * tried to rely on it). So now multiple ARMv8
124 * systems in the wild have different /proc/cpuinfo
125 * output, some of which are downright useless.
127 * So, when it comes to detecting ARMv8 in a 32-bit
128 * program, it's better to just avoid /proc/cpuinfo
129 * entirely. Maybe in a decade or two, we won't
130 * have to worry about this mess that the Linux ARM
131 * maintainers created. One can hope.
134 mono_hwcap_arm_is_v5 = TRUE;
135 mono_hwcap_arm_is_v6 = TRUE;
136 mono_hwcap_arm_is_v7 = TRUE;
138 mono_hwcap_arm_has_vfp = TRUE;
139 mono_hwcap_arm_has_vfp3 = TRUE;
140 mono_hwcap_arm_has_vfp3_d16 = TRUE;
142 mono_hwcap_arm_has_thumb = TRUE;
143 mono_hwcap_arm_has_thumb2 = TRUE;
145 #endif
147 char buf [512];
148 char *line;
150 FILE *file = fopen ("/proc/cpuinfo", "r");
152 if (file) {
153 while ((line = fgets (buf, 512, file))) {
154 if (!strncmp (line, "Processor", 9) ||
155 !strncmp (line, "model name", 10)) {
156 char *ver = strstr (line, "(v");
158 if (ver) {
159 if (ver [2] >= '5')
160 mono_hwcap_arm_is_v5 = TRUE;
162 if (ver [2] >= '6')
163 mono_hwcap_arm_is_v6 = TRUE;
165 if (ver [2] >= '7')
166 mono_hwcap_arm_is_v7 = TRUE;
168 /* TODO: Find a way to detect v7s. */
171 continue;
174 if (!strncmp (line, "Features", 8)) {
175 if (strstr (line, "thumb"))
176 mono_hwcap_arm_has_thumb = TRUE;
178 /* TODO: Find a way to detect Thumb 2. */
180 if (strstr (line, "vfp"))
181 mono_hwcap_arm_has_vfp = TRUE;
183 if (strstr (line, "vfpv3"))
184 mono_hwcap_arm_has_vfp3 = TRUE;
186 if (strstr (line, "vfpv3-d16"))
187 mono_hwcap_arm_has_vfp3_d16 = TRUE;
189 continue;
193 fclose (file);
195 #endif