util: Add cpuinfo-aarch64.c

Move the code from tcg/.  The only use of these bits so far
is with respect to the atomicity of tcg operations.

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2023-05-18 03:50:45 +00:00
parent b5c0d842d6
commit 0dd0c7fa20
5 changed files with 96 additions and 43 deletions

View File

@ -0,0 +1,22 @@
/*
* SPDX-License-Identifier: GPL-2.0-or-later
* Host specific cpu indentification for AArch64.
*/
#ifndef HOST_CPUINFO_H
#define HOST_CPUINFO_H
#define CPUINFO_ALWAYS (1u << 0) /* so cpuinfo is nonzero */
#define CPUINFO_LSE (1u << 1)
#define CPUINFO_LSE2 (1u << 2)
/* Initialized with a constructor. */
extern unsigned cpuinfo;
/*
* We cannot rely on constructor ordering, so other constructors must
* use the function interface rather than the variable above.
*/
unsigned cpuinfo_init(void);
#endif /* HOST_CPUINFO_H */

View File

@ -13,12 +13,6 @@
#include "../tcg-ldst.c.inc" #include "../tcg-ldst.c.inc"
#include "../tcg-pool.c.inc" #include "../tcg-pool.c.inc"
#include "qemu/bitops.h" #include "qemu/bitops.h"
#ifdef __linux__
#include <asm/hwcap.h>
#endif
#ifdef CONFIG_DARWIN
#include <sys/sysctl.h>
#endif
/* We're going to re-use TCGType in setting of the SF bit, which controls /* We're going to re-use TCGType in setting of the SF bit, which controls
the size of the operation performed. If we know the values match, it the size of the operation performed. If we know the values match, it
@ -77,9 +71,6 @@ static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot)
return TCG_REG_X0 + slot; return TCG_REG_X0 + slot;
} }
bool have_lse;
bool have_lse2;
#define TCG_REG_TMP TCG_REG_X30 #define TCG_REG_TMP TCG_REG_X30
#define TCG_VEC_TMP TCG_REG_V31 #define TCG_VEC_TMP TCG_REG_V31
@ -2878,39 +2869,8 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
} }
} }
#ifdef CONFIG_DARWIN
static bool sysctl_for_bool(const char *name)
{
int val = 0;
size_t len = sizeof(val);
if (sysctlbyname(name, &val, &len, NULL, 0) == 0) {
return val != 0;
}
/*
* We might in the future ask for properties not present in older kernels,
* but we're only asking about static properties, all of which should be
* 'int'. So we shouln't see ENOMEM (val too small), or any of the other
* more exotic errors.
*/
assert(errno == ENOENT);
return false;
}
#endif
static void tcg_target_init(TCGContext *s) static void tcg_target_init(TCGContext *s)
{ {
#ifdef __linux__
unsigned long hwcap = qemu_getauxval(AT_HWCAP);
have_lse = hwcap & HWCAP_ATOMICS;
have_lse2 = hwcap & HWCAP_USCAT;
#endif
#ifdef CONFIG_DARWIN
have_lse = sysctl_for_bool("hw.optional.arm.FEAT_LSE");
have_lse2 = sysctl_for_bool("hw.optional.arm.FEAT_LSE2");
#endif
tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffffu; tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffffu;
tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffffu; tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffffu;
tcg_target_available_regs[TCG_TYPE_V64] = 0xffffffff00000000ull; tcg_target_available_regs[TCG_TYPE_V64] = 0xffffffff00000000ull;

View File

@ -13,6 +13,8 @@
#ifndef AARCH64_TCG_TARGET_H #ifndef AARCH64_TCG_TARGET_H
#define AARCH64_TCG_TARGET_H #define AARCH64_TCG_TARGET_H
#include "host/cpuinfo.h"
#define TCG_TARGET_INSN_UNIT_SIZE 4 #define TCG_TARGET_INSN_UNIT_SIZE 4
#define TCG_TARGET_TLB_DISPLACEMENT_BITS 24 #define TCG_TARGET_TLB_DISPLACEMENT_BITS 24
#define MAX_CODE_GEN_BUFFER_SIZE ((size_t)-1) #define MAX_CODE_GEN_BUFFER_SIZE ((size_t)-1)
@ -57,8 +59,8 @@ typedef enum {
#define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_EVEN #define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_EVEN
#define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_NORMAL #define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_NORMAL
extern bool have_lse; #define have_lse (cpuinfo & CPUINFO_LSE)
extern bool have_lse2; #define have_lse2 (cpuinfo & CPUINFO_LSE2)
/* optional instructions */ /* optional instructions */
#define TCG_TARGET_HAS_div_i32 1 #define TCG_TARGET_HAS_div_i32 1

67
util/cpuinfo-aarch64.c Normal file
View File

@ -0,0 +1,67 @@
/*
* SPDX-License-Identifier: GPL-2.0-or-later
* Host specific cpu indentification for AArch64.
*/
#include "qemu/osdep.h"
#include "host/cpuinfo.h"
#ifdef CONFIG_LINUX
# ifdef CONFIG_GETAUXVAL
# include <sys/auxv.h>
# else
# include <asm/hwcap.h>
# include "elf.h"
# endif
#endif
#ifdef CONFIG_DARWIN
# include <sys/sysctl.h>
#endif
unsigned cpuinfo;
#ifdef CONFIG_DARWIN
static bool sysctl_for_bool(const char *name)
{
int val = 0;
size_t len = sizeof(val);
if (sysctlbyname(name, &val, &len, NULL, 0) == 0) {
return val != 0;
}
/*
* We might in the future ask for properties not present in older kernels,
* but we're only asking about static properties, all of which should be
* 'int'. So we shouln't see ENOMEM (val too small), or any of the other
* more exotic errors.
*/
assert(errno == ENOENT);
return false;
}
#endif
/* Called both as constructor and (possibly) via other constructors. */
unsigned __attribute__((constructor)) cpuinfo_init(void)
{
unsigned info = cpuinfo;
if (info) {
return info;
}
info = CPUINFO_ALWAYS;
#ifdef CONFIG_LINUX
unsigned long hwcap = qemu_getauxval(AT_HWCAP);
info |= (hwcap & HWCAP_ATOMICS ? CPUINFO_LSE : 0);
info |= (hwcap & HWCAP_USCAT ? CPUINFO_LSE2 : 0);
#endif
#ifdef CONFIG_DARWIN
info |= sysctl_for_bool("hw.optional.arm.FEAT_LSE") * CPUINFO_LSE;
info |= sysctl_for_bool("hw.optional.arm.FEAT_LSE2") * CPUINFO_LSE2;
#endif
cpuinfo = info;
return info;
}

View File

@ -109,6 +109,8 @@ if have_block
util_ss.add(when: 'CONFIG_LINUX', if_true: files('vfio-helpers.c')) util_ss.add(when: 'CONFIG_LINUX', if_true: files('vfio-helpers.c'))
endif endif
if cpu in ['x86', 'x86_64'] if cpu == 'aarch64'
util_ss.add(files('cpuinfo-aarch64.c'))
elif cpu in ['x86', 'x86_64']
util_ss.add(files('cpuinfo-i386.c')) util_ss.add(files('cpuinfo-i386.c'))
endif endif