1 /* 2 * SPDX-License-Identifier: GPL-2.0-or-later 3 * Host specific cpu identification for AArch64. 4 */ 5 6 #include "qemu/osdep.h" 7 #include "host/cpuinfo.h" 8 9 #ifdef CONFIG_LINUX 10 # ifdef CONFIG_GETAUXVAL 11 # include <sys/auxv.h> 12 # else 13 # include <asm/hwcap.h> 14 # include "elf.h" 15 # endif 16 # ifndef HWCAP2_BTI 17 # define HWCAP2_BTI 0 /* added in glibc 2.32 */ 18 # endif 19 #endif 20 #ifdef CONFIG_DARWIN 21 # include <sys/sysctl.h> 22 #endif 23 24 unsigned cpuinfo; 25 26 #ifdef CONFIG_DARWIN 27 static bool sysctl_for_bool(const char *name) 28 { 29 int val = 0; 30 size_t len = sizeof(val); 31 32 if (sysctlbyname(name, &val, &len, NULL, 0) == 0) { 33 return val != 0; 34 } 35 36 /* 37 * We might in the future ask for properties not present in older kernels, 38 * but we're only asking about static properties, all of which should be 39 * 'int'. So we shouldn't see ENOMEM (val too small), or any of the other 40 * more exotic errors. 41 */ 42 assert(errno == ENOENT); 43 return false; 44 } 45 #endif 46 47 /* Called both as constructor and (possibly) via other constructors. */ 48 unsigned __attribute__((constructor)) cpuinfo_init(void) 49 { 50 unsigned info = cpuinfo; 51 52 if (info) { 53 return info; 54 } 55 56 info = CPUINFO_ALWAYS; 57 58 #ifdef CONFIG_LINUX 59 unsigned long hwcap = qemu_getauxval(AT_HWCAP); 60 info |= (hwcap & HWCAP_ATOMICS ? CPUINFO_LSE : 0); 61 info |= (hwcap & HWCAP_USCAT ? CPUINFO_LSE2 : 0); 62 info |= (hwcap & HWCAP_AES ? CPUINFO_AES : 0); 63 info |= (hwcap & HWCAP_PMULL ? CPUINFO_PMULL : 0); 64 65 unsigned long hwcap2 = qemu_getauxval(AT_HWCAP2); 66 info |= (hwcap2 & HWCAP2_BTI ? CPUINFO_BTI : 0); 67 #endif 68 #ifdef CONFIG_DARWIN 69 info |= sysctl_for_bool("hw.optional.arm.FEAT_LSE") * CPUINFO_LSE; 70 info |= sysctl_for_bool("hw.optional.arm.FEAT_LSE2") * CPUINFO_LSE2; 71 info |= sysctl_for_bool("hw.optional.arm.FEAT_AES") * CPUINFO_AES; 72 info |= sysctl_for_bool("hw.optional.arm.FEAT_PMULL") * CPUINFO_PMULL; 73 info |= sysctl_for_bool("hw.optional.arm.FEAT_BTI") * CPUINFO_BTI; 74 #endif 75 76 cpuinfo = info; 77 return info; 78 } 79