aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--host/include/ppc/host/cpuinfo.h29
-rw-r--r--host/include/ppc64/host/cpuinfo.h1
-rw-r--r--tcg/ppc/tcg-target.c.inc44
-rw-r--r--tcg/ppc/tcg-target.h16
-rw-r--r--util/cpuinfo-ppc.c56
-rw-r--r--util/meson.build2
6 files changed, 97 insertions, 51 deletions
diff --git a/host/include/ppc/host/cpuinfo.h b/host/include/ppc/host/cpuinfo.h
new file mode 100644
index 0000000000..df11e8d417
--- /dev/null
+++ b/host/include/ppc/host/cpuinfo.h
@@ -0,0 +1,29 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Host specific cpu indentification for ppc.
+ */
+
+#ifndef HOST_CPUINFO_H
+#define HOST_CPUINFO_H
+
+/* Digested version of <cpuid.h> */
+
+#define CPUINFO_ALWAYS (1u << 0) /* so cpuinfo is nonzero */
+#define CPUINFO_V2_06 (1u << 1)
+#define CPUINFO_V2_07 (1u << 2)
+#define CPUINFO_V3_0 (1u << 3)
+#define CPUINFO_V3_1 (1u << 4)
+#define CPUINFO_ISEL (1u << 5)
+#define CPUINFO_ALTIVEC (1u << 6)
+#define CPUINFO_VSX (1u << 7)
+
+/* 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 */
diff --git a/host/include/ppc64/host/cpuinfo.h b/host/include/ppc64/host/cpuinfo.h
new file mode 100644
index 0000000000..2f036a0627
--- /dev/null
+++ b/host/include/ppc64/host/cpuinfo.h
@@ -0,0 +1 @@
+#include "host/include/ppc/host/cpuinfo.h"
diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
index 5c8378f8f6..c866f2c997 100644
--- a/tcg/ppc/tcg-target.c.inc
+++ b/tcg/ppc/tcg-target.c.inc
@@ -101,10 +101,7 @@
#define ALL_GENERAL_REGS 0xffffffffu
#define ALL_VECTOR_REGS 0xffffffff00000000ull
-TCGPowerISA have_isa;
-static bool have_isel;
-bool have_altivec;
-bool have_vsx;
+#define have_isel (cpuinfo & CPUINFO_ISEL)
#ifndef CONFIG_SOFTMMU
#define TCG_GUEST_BASE_REG 30
@@ -3879,45 +3876,6 @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
static void tcg_target_init(TCGContext *s)
{
- unsigned long hwcap = qemu_getauxval(AT_HWCAP);
- unsigned long hwcap2 = qemu_getauxval(AT_HWCAP2);
-
- have_isa = tcg_isa_base;
- if (hwcap & PPC_FEATURE_ARCH_2_06) {
- have_isa = tcg_isa_2_06;
- }
-#ifdef PPC_FEATURE2_ARCH_2_07
- if (hwcap2 & PPC_FEATURE2_ARCH_2_07) {
- have_isa = tcg_isa_2_07;
- }
-#endif
-#ifdef PPC_FEATURE2_ARCH_3_00
- if (hwcap2 & PPC_FEATURE2_ARCH_3_00) {
- have_isa = tcg_isa_3_00;
- }
-#endif
-#ifdef PPC_FEATURE2_ARCH_3_10
- if (hwcap2 & PPC_FEATURE2_ARCH_3_10) {
- have_isa = tcg_isa_3_10;
- }
-#endif
-
-#ifdef PPC_FEATURE2_HAS_ISEL
- /* Prefer explicit instruction from the kernel. */
- have_isel = (hwcap2 & PPC_FEATURE2_HAS_ISEL) != 0;
-#else
- /* Fall back to knowing Power7 (2.06) has ISEL. */
- have_isel = have_isa_2_06;
-#endif
-
- if (hwcap & PPC_FEATURE_HAS_ALTIVEC) {
- have_altivec = true;
- /* We only care about the portion of VSX that overlaps Altivec. */
- if (hwcap & PPC_FEATURE_HAS_VSX) {
- have_vsx = true;
- }
- }
-
tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffff;
tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffff;
if (have_altivec) {
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
index c7552b6391..9a41fab8cc 100644
--- a/tcg/ppc/tcg-target.h
+++ b/tcg/ppc/tcg-target.h
@@ -25,6 +25,8 @@
#ifndef PPC_TCG_TARGET_H
#define PPC_TCG_TARGET_H
+#include "host/cpuinfo.h"
+
#define MAX_CODE_GEN_BUFFER_SIZE ((size_t)-1)
#define TCG_TARGET_NB_REGS 64
@@ -61,14 +63,12 @@ typedef enum {
tcg_isa_3_10,
} TCGPowerISA;
-extern TCGPowerISA have_isa;
-extern bool have_altivec;
-extern bool have_vsx;
-
-#define have_isa_2_06 (have_isa >= tcg_isa_2_06)
-#define have_isa_2_07 (have_isa >= tcg_isa_2_07)
-#define have_isa_3_00 (have_isa >= tcg_isa_3_00)
-#define have_isa_3_10 (have_isa >= tcg_isa_3_10)
+#define have_isa_2_06 (cpuinfo & CPUINFO_V2_06)
+#define have_isa_2_07 (cpuinfo & CPUINFO_V2_07)
+#define have_isa_3_00 (cpuinfo & CPUINFO_V3_0)
+#define have_isa_3_10 (cpuinfo & CPUINFO_V3_1)
+#define have_altivec (cpuinfo & CPUINFO_ALTIVEC)
+#define have_vsx (cpuinfo & CPUINFO_VSX)
/* optional instructions automatically implemented */
#define TCG_TARGET_HAS_ext8u_i32 0 /* andi */
diff --git a/util/cpuinfo-ppc.c b/util/cpuinfo-ppc.c
new file mode 100644
index 0000000000..d95adc8ccd
--- /dev/null
+++ b/util/cpuinfo-ppc.c
@@ -0,0 +1,56 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Host specific cpu indentification for ppc.
+ */
+
+#include "qemu/osdep.h"
+#include "host/cpuinfo.h"
+
+#ifdef CONFIG_GETAUXVAL
+# include <sys/auxv.h>
+#else
+# include <asm/cputable.h>
+# include "elf.h"
+#endif
+
+unsigned cpuinfo;
+
+/* Called both as constructor and (possibly) via other constructors. */
+unsigned __attribute__((constructor)) cpuinfo_init(void)
+{
+ unsigned info = cpuinfo;
+ unsigned long hwcap, hwcap2;
+
+ if (info) {
+ return info;
+ }
+
+ hwcap = qemu_getauxval(AT_HWCAP);
+ hwcap2 = qemu_getauxval(AT_HWCAP2);
+ info = CPUINFO_ALWAYS;
+
+ /* Version numbers are monotonic, and so imply all lower versions. */
+ if (hwcap2 & PPC_FEATURE2_ARCH_3_1) {
+ info |= CPUINFO_V3_1 | CPUINFO_V3_0 | CPUINFO_V2_07 | CPUINFO_V2_06;
+ } else if (hwcap2 & PPC_FEATURE2_ARCH_3_00) {
+ info |= CPUINFO_V3_0 | CPUINFO_V2_07 | CPUINFO_V2_06;
+ } else if (hwcap2 & PPC_FEATURE2_ARCH_2_07) {
+ info |= CPUINFO_V2_07 | CPUINFO_V2_06;
+ } else if (hwcap & PPC_FEATURE_ARCH_2_06) {
+ info |= CPUINFO_V2_06;
+ }
+
+ if (hwcap2 & PPC_FEATURE2_HAS_ISEL) {
+ info |= CPUINFO_ISEL;
+ }
+ if (hwcap & PPC_FEATURE_HAS_ALTIVEC) {
+ info |= CPUINFO_ALTIVEC;
+ /* We only care about the portion of VSX that overlaps Altivec. */
+ if (hwcap & PPC_FEATURE_HAS_VSX) {
+ info |= CPUINFO_VSX;
+ }
+ }
+
+ cpuinfo = info;
+ return info;
+}
diff --git a/util/meson.build b/util/meson.build
index 3a93071d27..a375160286 100644
--- a/util/meson.build
+++ b/util/meson.build
@@ -113,4 +113,6 @@ if cpu == 'aarch64'
util_ss.add(files('cpuinfo-aarch64.c'))
elif cpu in ['x86', 'x86_64']
util_ss.add(files('cpuinfo-i386.c'))
+elif cpu in ['ppc', 'ppc64']
+ util_ss.add(files('cpuinfo-ppc.c'))
endif