qemu/util/cpuinfo-aarch64.c
<<
>>
Prefs
   1/*
   2 * SPDX-License-Identifier: GPL-2.0-or-later
   3 * Host specific cpu indentification 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#endif
  17#ifdef CONFIG_DARWIN
  18# include <sys/sysctl.h>
  19#endif
  20
  21unsigned cpuinfo;
  22
  23#ifdef CONFIG_DARWIN
  24static bool sysctl_for_bool(const char *name)
  25{
  26    int val = 0;
  27    size_t len = sizeof(val);
  28
  29    if (sysctlbyname(name, &val, &len, NULL, 0) == 0) {
  30        return val != 0;
  31    }
  32
  33    /*
  34     * We might in the future ask for properties not present in older kernels,
  35     * but we're only asking about static properties, all of which should be
  36     * 'int'.  So we shouln't see ENOMEM (val too small), or any of the other
  37     * more exotic errors.
  38     */
  39    assert(errno == ENOENT);
  40    return false;
  41}
  42#endif
  43
  44/* Called both as constructor and (possibly) via other constructors. */
  45unsigned __attribute__((constructor)) cpuinfo_init(void)
  46{
  47    unsigned info = cpuinfo;
  48
  49    if (info) {
  50        return info;
  51    }
  52
  53    info = CPUINFO_ALWAYS;
  54
  55#ifdef CONFIG_LINUX
  56    unsigned long hwcap = qemu_getauxval(AT_HWCAP);
  57    info |= (hwcap & HWCAP_ATOMICS ? CPUINFO_LSE : 0);
  58    info |= (hwcap & HWCAP_USCAT ? CPUINFO_LSE2 : 0);
  59    info |= (hwcap & HWCAP_AES ? CPUINFO_AES: 0);
  60#endif
  61#ifdef CONFIG_DARWIN
  62    info |= sysctl_for_bool("hw.optional.arm.FEAT_LSE") * CPUINFO_LSE;
  63    info |= sysctl_for_bool("hw.optional.arm.FEAT_LSE2") * CPUINFO_LSE2;
  64    info |= sysctl_for_bool("hw.optional.arm.FEAT_AES") * CPUINFO_AES;
  65#endif
  66
  67    cpuinfo = info;
  68    return info;
  69}
  70