xref: /openbmc/qemu/util/cpuinfo-aarch64.c (revision 095859e5)
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 Henderson static 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 Henderson unsigned __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