On 7/13/26 04:36, Matt Turner wrote:
Alpha has never set AT_HWCAP in linux-user emulation, so getauxval(AT_HWCAP)
always returned 0 regardless of the emulated CPU model.

The Linux kernel computes ELF_HWCAP as ~amask(-1), i.e. the set of ISA
extension bits that the amask instruction reports as supported (cleared in
its output).  env->amask stores exactly those bits with the same layout
(BWX=0x1, FIX=0x2, CIX=0x4, MVI=0x100, TRAP=0x200, PREFETCH=0x1000), so
returning it directly from get_elf_hwcap matches the kernel convention.

Add HAVE_ELF_HWCAP to target_elf.h and implement get_elf_hwcap() in
elfload.c to expose the emulated CPU's capability mask to user-space
programs via the auxiliary vector.

Without this fix, programs using getauxval(AT_HWCAP) to detect BWX/FIX/CIX
(such as glibc's memcpy or JIT compilers targeting Alpha) incorrectly
concluded that no extensions were available even when emulating ev56+.

In stable 10.0.x qemu series, things are different from what we have
now, - there, everything is in single linux-user/elfload.c and the
context is a bit different too.

Here's my backport of this change to 10.0.x:
https://gitlab.com/mjt0k/qemu/-/commit/e4c1bf9b1fe030ef1d0d4c74086cccb62c6b0442

I appreciate a quick look at the result, whenever it looks good for
10.0.x or not.

Thanks,

/mjt

  linux-user/alpha/elfload.c    | 11 +++++++++++
  linux-user/alpha/target_elf.h |  1 +
  2 files changed, 12 insertions(+)

diff --git ./linux-user/alpha/elfload.c ./linux-user/alpha/elfload.c
index 1969f620a5..7be9e466b6 100644
--- ./linux-user/alpha/elfload.c
+++ ./linux-user/alpha/elfload.c
@@ -6,6 +6,17 @@
  #include "target_elf.h"
+abi_ulong get_elf_hwcap(CPUState *cs)
+{
+    /*
+     * The Linux kernel computes ELF_HWCAP as ~amask(-1), which clears a bit
+     * for each supported ISA extension.  env->amask stores exactly those bits
+     * set for the extensions supported by the emulated CPU model, matching
+     * the kernel's convention: bit set in AT_HWCAP ↔ extension present.
+     */
+    return cpu_env(cs)->amask;
+}
+
  void elf_core_copy_regs(target_elf_gregset_t *r, const CPUAlphaState *env)
  {
      int i;
diff --git ./linux-user/alpha/target_elf.h ./linux-user/alpha/target_elf.h
index 4987ae3944..dd90c6f783 100644
--- ./linux-user/alpha/target_elf.h
+++ ./linux-user/alpha/target_elf.h
@@ -12,6 +12,7 @@
  #define ELF_MACHINE             EM_ALPHA
#define HAVE_ELF_CORE_DUMP 1
+#define HAVE_ELF_HWCAP          1
/*
   * Matches the kernel's elf_gregset_t (ELF_NGREG = 33):


Reply via email to