[PATCH 3/3] host/aarch64: Implement atomic64_{read, set} with FEAT_LS64

Richard Henderson <[email protected]>
Newsgroups org.nongnu.qemu-arm,org.nongnu.qemu-devel
Message-ID <[email protected]>
Detect the host feature in cpuid, then use it.

Signed-off-by: Richard Henderson <[email protected]>
---
 host/include/aarch64/host/cpuinfo.h           |  1 +
 include/qemu/value64.h                        |  7 ++++
 util/cpuinfo-aarch64.c                        | 14 ++++++--
 .../include/aarch64/host/atomic512-ldst.h.inc | 36 +++++++++++++++++++
 meson.build                                   |  8 +++++
 5 files changed, 63 insertions(+), 3 deletions(-)
 create mode 100644 host/include/aarch64/host/atomic512-ldst.h.inc

diff --git a/host/include/aarch64/host/cpuinfo.h b/host/include/aarch64/host/cpuinfo.h
index fe671534e4..ac3a224fc3 100644
--- a/host/include/aarch64/host/cpuinfo.h
+++ b/host/include/aarch64/host/cpuinfo.h
@@ -12,6 +12,7 @@
 #define CPUINFO_AES             (1u << 3)
 #define CPUINFO_PMULL           (1u << 4)
 #define CPUINFO_BTI             (1u << 5)
+#define CPUINFO_LS64            (1u << 6)
 
 /* Initialized with a constructor. */
 extern unsigned cpuinfo;
diff --git a/include/qemu/value64.h b/include/qemu/value64.h
index 7de287a13d..b74316bf82 100644
--- a/include/qemu/value64.h
+++ b/include/qemu/value64.h
@@ -3,12 +3,19 @@
 #ifndef QEMU_VALUE64_H
 #define QEMU_VALUE64_H
 
+#ifdef __aarch64__
+#include <arm_acle.h>
+#endif
+
 /*
  * An stream of 64 bytes; no endianness implied.
  * The members are perforce host byte ordering.
  */
 typedef union {
     uint64_t l[8];
+#ifdef __aarch64__
+    data512_t arm;
+#endif
 } Value64;
 
 #endif /* QEMU_VALUE64_H */
diff --git a/util/cpuinfo-aarch64.c b/util/cpuinfo-aarch64.c
index 288074c08f..0a01050626 100644
--- a/util/cpuinfo-aarch64.c
+++ b/util/cpuinfo-aarch64.c
@@ -13,9 +13,6 @@
 #  include <asm/hwcap.h>
 #  include "elf.h"
 # endif
-# ifndef HWCAP2_BTI
-#  define HWCAP2_BTI 0  /* added in glibc 2.32 */
-# endif
 #endif
 #ifdef CONFIG_ELF_AUX_INFO
 #include <sys/auxv.h>
@@ -29,6 +26,13 @@
 # include <sys/sysctl.h>
 #endif
 
+#ifndef HWCAP2_BTI
+# define HWCAP2_BTI 0  /* added in glibc 2.32 */
+#endif
+#ifndef HWCAP3_LS64
+# define HWCAP3_LS64 0 /* added in glibc 2.44 */
+#endif
+
 unsigned cpuinfo;
 
 #ifdef CONFIG_DARWIN
@@ -72,6 +76,9 @@ unsigned __attribute__((constructor)) cpuinfo_init(void)
 
     unsigned long hwcap2 = qemu_getauxval(AT_HWCAP2);
     info |= (hwcap2 & HWCAP2_BTI ? CPUINFO_BTI : 0);
+
+    unsigned long hwcap3 = qemu_getauxval(AT_HWCAP3);
+    info |= (hwcap3 & HWCAP3_LS64 ? CPUINFO_LS64 : 0);
 #endif
 #ifdef CONFIG_DARWIN
     info |= sysctl_for_bool("hw.optional.arm.FEAT_LSE") * CPUINFO_LSE;
@@ -79,6 +86,7 @@ unsigned __attribute__((constructor)) cpuinfo_init(void)
     info |= sysctl_for_bool("hw.optional.arm.FEAT_AES") * CPUINFO_AES;
     info |= sysctl_for_bool("hw.optional.arm.FEAT_PMULL") * CPUINFO_PMULL;
     info |= sysctl_for_bool("hw.optional.arm.FEAT_BTI") * CPUINFO_BTI;
+    info |= sysctl_for_bool("hw.optional.arm.FEAT_LS64") * CPUINFO_LS64;
 #endif
 #if defined(__OpenBSD__) && !defined(CONFIG_ELF_AUX_INFO)
     int mib[2];
diff --git a/host/include/aarch64/host/atomic512-ldst.h.inc b/host/include/aarch64/host/atomic512-ldst.h.inc
new file mode 100644
index 0000000000..a254560be7
--- /dev/null
+++ b/host/include/aarch64/host/atomic512-ldst.h.inc
@@ -0,0 +1,36 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Load/store for 512-bit atomic operations, AArch64 version.
+ */
+
+#ifndef HOST_ATOMIC512_LDST_H
+#define HOST_ATOMIC512_LDST_H
+
+#ifdef CONFIG_ARM_LS64_BUILTIN
+#include "host/cpuinfo.h"
+#include <arm_acle.h>
+
+#ifdef __ARM_FEATURE_LS64
+# define HAVE_ATOMIC512_LD  true
+# define ATTR_LS64_ACCEL
+#else
+# define HAVE_ATOMIC512_LD  likely(cpuinfo & CPUINFO_LS64)
+# define ATTR_LS64_ACCEL  __attribute__((target("+ls64")))
+#endif
+#define HAVE_ATOMIC512_ST   HAVE_ATOMIC512_LD
+
+static inline Value64 ATTR_LS64_ACCEL atomic64_read(const void *s)
+{
+    return (Value64){ .arm = __arm_ld64b(s) };
+}
+
+static inline void ATTR_LS64_ACCEL atomic64_set(void *d, const Value64 *v)
+{
+    __arm_st64b(d, v->arm);
+}
+
+#else
+#include "host/include/generic/host/atomic512-ldst.h.inc"
+#endif
+
+#endif /* HOST_ATOMIC512_LDST_H */
diff --git a/meson.build b/meson.build
index 164328ded8..5afeda83fd 100644
--- a/meson.build
+++ b/meson.build
@@ -3106,6 +3106,14 @@ config_host_data.set('CONFIG_ARM_AES_BUILTIN', cc.compiles('''
     void foo(uint8x16_t *p) { *p = vaesmcq_u8(*p); }
   '''))
 
+config_host_data.set('CONFIG_ARM_LS64_BUILTIN', cc.compiles('''
+    #include <arm_acle.h>
+    #ifndef __ARM_FEATURE_LS64
+    __attribute__((target("+ls64")))
+    #endif
+    void foo(void *p, void *q) { __arm_st64b(q, __arm_ld64b(p)); }
+  '''))
+
 if get_option('membarrier').disabled()
   have_membarrier = false
 elif host_os == 'windows'
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.