linux-user/alpha/elfload.c | 11 +++++++++++ linux-user/alpha/target_elf.h | 1 + 2 files changed, 12 insertions(+)
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+.
---
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):
--
2.54.0
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):
On Wed, Jul 15, 2026 at 7:23 AM Michael Tokarev <mjt@tls.msk.ru> wrote: > > 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. Looks good to me. Thank you!
On 7/13/26 03: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+. > --- > linux-user/alpha/elfload.c | 11 +++++++++++ > linux-user/alpha/target_elf.h | 1 + > 2 files changed, 12 insertions(+) Reviewed-by: Helge Deller <deller@gmx.de> I'll include this patch in the next linux-user pull request. Helge
© 2016 - 2026 Red Hat, Inc.