10dd0c7faSRichard Henderson /* 20dd0c7faSRichard Henderson * SPDX-License-Identifier: GPL-2.0-or-later 3d02d06f8SMichael Tokarev * Host specific cpu identification for AArch64. 40dd0c7faSRichard Henderson */ 50dd0c7faSRichard Henderson 60dd0c7faSRichard Henderson #include "qemu/osdep.h" 70dd0c7faSRichard Henderson #include "host/cpuinfo.h" 80dd0c7faSRichard Henderson 90dd0c7faSRichard Henderson #ifdef CONFIG_LINUX 100dd0c7faSRichard Henderson # ifdef CONFIG_GETAUXVAL 110dd0c7faSRichard Henderson # include <sys/auxv.h> 120dd0c7faSRichard Henderson # else 130dd0c7faSRichard Henderson # include <asm/hwcap.h> 140dd0c7faSRichard Henderson # include "elf.h" 150dd0c7faSRichard Henderson # endif 16*095859e5SRichard Henderson # ifndef HWCAP2_BTI 17*095859e5SRichard Henderson # define HWCAP2_BTI 0 /* added in glibc 2.32 */ 18*095859e5SRichard Henderson # endif 190dd0c7faSRichard Henderson #endif 200dd0c7faSRichard Henderson #ifdef CONFIG_DARWIN 210dd0c7faSRichard Henderson # include <sys/sysctl.h> 220dd0c7faSRichard Henderson #endif 230dd0c7faSRichard Henderson 240dd0c7faSRichard Henderson unsigned cpuinfo; 250dd0c7faSRichard Henderson 260dd0c7faSRichard Henderson #ifdef CONFIG_DARWIN sysctl_for_bool(const char * name)270dd0c7faSRichard Hendersonstatic bool sysctl_for_bool(const char *name) 280dd0c7faSRichard Henderson { 290dd0c7faSRichard Henderson int val = 0; 300dd0c7faSRichard Henderson size_t len = sizeof(val); 310dd0c7faSRichard Henderson 320dd0c7faSRichard Henderson if (sysctlbyname(name, &val, &len, NULL, 0) == 0) { 330dd0c7faSRichard Henderson return val != 0; 340dd0c7faSRichard Henderson } 350dd0c7faSRichard Henderson 360dd0c7faSRichard Henderson /* 370dd0c7faSRichard Henderson * We might in the future ask for properties not present in older kernels, 380dd0c7faSRichard Henderson * but we're only asking about static properties, all of which should be 39d02d06f8SMichael Tokarev * 'int'. So we shouldn't see ENOMEM (val too small), or any of the other 400dd0c7faSRichard Henderson * more exotic errors. 410dd0c7faSRichard Henderson */ 420dd0c7faSRichard Henderson assert(errno == ENOENT); 430dd0c7faSRichard Henderson return false; 440dd0c7faSRichard Henderson } 450dd0c7faSRichard Henderson #endif 460dd0c7faSRichard Henderson 470dd0c7faSRichard Henderson /* Called both as constructor and (possibly) via other constructors. */ cpuinfo_init(void)480dd0c7faSRichard Hendersonunsigned __attribute__((constructor)) cpuinfo_init(void) 490dd0c7faSRichard Henderson { 500dd0c7faSRichard Henderson unsigned info = cpuinfo; 510dd0c7faSRichard Henderson 520dd0c7faSRichard Henderson if (info) { 530dd0c7faSRichard Henderson return info; 540dd0c7faSRichard Henderson } 550dd0c7faSRichard Henderson 560dd0c7faSRichard Henderson info = CPUINFO_ALWAYS; 570dd0c7faSRichard Henderson 580dd0c7faSRichard Henderson #ifdef CONFIG_LINUX 590dd0c7faSRichard Henderson unsigned long hwcap = qemu_getauxval(AT_HWCAP); 600dd0c7faSRichard Henderson info |= (hwcap & HWCAP_ATOMICS ? CPUINFO_LSE : 0); 610dd0c7faSRichard Henderson info |= (hwcap & HWCAP_USCAT ? CPUINFO_LSE2 : 0); 628d97f28eSRichard Henderson info |= (hwcap & HWCAP_AES ? CPUINFO_AES : 0); 63*095859e5SRichard Henderson info |= (hwcap & HWCAP_PMULL ? CPUINFO_PMULL : 0); 64*095859e5SRichard Henderson 65*095859e5SRichard Henderson unsigned long hwcap2 = qemu_getauxval(AT_HWCAP2); 660dd0c7faSRichard Henderson info |= (hwcap2 & HWCAP2_BTI ? CPUINFO_BTI : 0); 670dd0c7faSRichard Henderson #endif 680dd0c7faSRichard Henderson #ifdef CONFIG_DARWIN 690dd0c7faSRichard Henderson info |= sysctl_for_bool("hw.optional.arm.FEAT_LSE") * CPUINFO_LSE; 708d97f28eSRichard Henderson info |= sysctl_for_bool("hw.optional.arm.FEAT_LSE2") * CPUINFO_LSE2; 71*095859e5SRichard Henderson info |= sysctl_for_bool("hw.optional.arm.FEAT_AES") * CPUINFO_AES; 720dd0c7faSRichard Henderson info |= sysctl_for_bool("hw.optional.arm.FEAT_PMULL") * CPUINFO_PMULL; 730dd0c7faSRichard Henderson info |= sysctl_for_bool("hw.optional.arm.FEAT_BTI") * CPUINFO_BTI; 740dd0c7faSRichard Henderson #endif 750dd0c7faSRichard Henderson 760dd0c7faSRichard Henderson cpuinfo = info; 77 return info; 78 } 79