* [PULL 0/4] Linux user patches
@ 2026-06-18 21:54 Helge Deller
2026-06-18 21:54 ` [PULL 1/4] linux-user: Fix AT_PHDR when program headers are relocated into their own segment Helge Deller
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Helge Deller @ 2026-06-18 21:54 UTC (permalink / raw)
To: qemu-devel, Stefan Hajnoczi; +Cc: Pierrick Bouvier, Laurent Vivier, deller
From: Helge Deller <deller@gmx.de>
The following changes since commit c7cf7c810153d6f5f31aa2d5c0dee9087f6b4dff:
Merge tag 'firmware-20260617-pull-request' of https://gitlab.com/kraxel/qemu into staging (2026-06-17 10:17:29 -0400)
are available in the Git repository at:
https://github.com/hdeller/qemu-hppa.git tags/linux-user-pull-request
for you to fetch changes up to 54e08dbe8f2aeca57e3b1a5eab09a9fec88c1c67:
linux-user/xtensa: fix unlock of uninitialized frame pointer on sigreturn (2026-06-18 23:43:35 +0200)
----------------------------------------------------------------
linux-user patches
One frame pointer memory locking fix for the xtensa architecture, a generic
loader fix for programs with modified headers, and two patches to emulate
/proc/cpuinfo for loogarch and m68k CPUs.
----------------------------------------------------------------
Akshit Yadav (1):
linux-user: Fix AT_PHDR when program headers are relocated into their
own segment
Helge Deller (2):
linux-user: Implement /proc/cpuinfo for loongarch cpus
linux-user: Implement /proc/cpuinfo for m68k CPU
Matt Turner (1):
linux-user/xtensa: fix unlock of uninitialized frame pointer on
sigreturn
linux-user/elfload.c | 21 +++++++-
linux-user/loongarch64/elfload.c | 20 +++++++
linux-user/loongarch64/target_proc.h | 79 +++++++++++++++++++++++++++-
linux-user/m68k/target_proc.h | 46 ++++++++++++++++
linux-user/qemu.h | 1 +
linux-user/xtensa/signal.c | 3 +-
6 files changed, 167 insertions(+), 3 deletions(-)
--
2.54.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PULL 1/4] linux-user: Fix AT_PHDR when program headers are relocated into their own segment
2026-06-18 21:54 [PULL 0/4] Linux user patches Helge Deller
@ 2026-06-18 21:54 ` Helge Deller
2026-06-18 21:54 ` [PULL 2/4] linux-user: Implement /proc/cpuinfo for loongarch cpus Helge Deller
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Helge Deller @ 2026-06-18 21:54 UTC (permalink / raw)
To: qemu-devel, Stefan Hajnoczi
Cc: Pierrick Bouvier, Laurent Vivier, deller, Akshit Yadav
From: Akshit Yadav <valium7171@gmail.com>
When a binary is patched or relocated such that the program header table is
moved into a separate PT_LOAD segment (rather than sitting at the start of the
first loadable segment), QEMU's AT_PHDR auxv entry becomes incorrect. The
loader was computing AT_PHDR as load_addr + e_phoff, which assumes the headers
are mapped 1:1 from file offset 0. This breaks when the headers are elsewhere.
The Linux kernel instead locates the PT_LOAD segment that contains e_phoff,
then computes the in-memory address as p_vaddr + (e_phoff - p_offset). This
correctly handles relocated headers.
Fix by:
1. Add phdr_addr field to image_info to cache the resolved address.
2. Initialize to load_addr + e_phoff (fallback for headers outside any PT_LOAD).
3. In the PT_LOAD mapping loop, detect if the segment contains e_phoff and
override with the segment-relative address.
4. Use info->phdr_addr for AT_PHDR instead of the incorrect formula.
Signed-off-by: Akshit Yadav <valium7171@gmail.com>
Reviewed-by: Helge Deller <deller@gmx.de>
---
linux-user/elfload.c | 21 ++++++++++++++++++++-
linux-user/qemu.h | 1 +
2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index b05b8b0c6b..8049c8ae62 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -699,7 +699,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
/* There must be exactly DLINFO_ITEMS entries here, or the assert
* on info->auxv_len will trigger.
*/
- NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->load_addr + exec->e_phoff));
+ NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->phdr_addr));
NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
@@ -1469,6 +1469,12 @@ static void load_elf_image(const char *image_name, const ImageSource *src,
info->data_offset = load_bias;
info->load_addr = load_addr;
info->entry = ehdr->e_entry + load_bias;
+ /*
+ * Fallback for AT_PHDR if the program headers do not fall within
+ * any PT_LOAD segment (see the loop below, which overrides this with
+ * the correct in-memory address when a containing segment is found).
+ */
+ info->phdr_addr = load_addr + ehdr->e_phoff;
info->start_code = -1;
info->end_code = 0;
info->start_data = -1;
@@ -1523,6 +1529,19 @@ static void load_elf_image(const char *image_name, const ImageSource *src,
vaddr_ef = vaddr + eppnt->p_filesz;
vaddr_em = vaddr + eppnt->p_memsz;
+ /*
+ * If this segment contains the program headers, record their
+ * in-memory address for AT_PHDR. This matches the kernel, which
+ * locates the headers via the containing PT_LOAD rather than
+ * assuming load_addr + e_phoff (false when the phdrs are not
+ * mapped 1:1 from file offset 0, e.g. relocated into their own
+ * segment by a binary patcher).
+ */
+ if (eppnt->p_offset <= ehdr->e_phoff &&
+ ehdr->e_phoff < eppnt->p_offset + eppnt->p_filesz) {
+ info->phdr_addr = vaddr + (ehdr->e_phoff - eppnt->p_offset);
+ }
+
/*
* Some segments may be completely empty, with a non-zero p_memsz
* but no backing file segment.
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 07fe801628..2268493141 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -26,6 +26,7 @@
struct image_info {
abi_ulong load_bias;
abi_ulong load_addr;
+ abi_ulong phdr_addr;
abi_ulong start_code;
abi_ulong end_code;
abi_ulong start_data;
--
2.54.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PULL 2/4] linux-user: Implement /proc/cpuinfo for loongarch cpus
2026-06-18 21:54 [PULL 0/4] Linux user patches Helge Deller
2026-06-18 21:54 ` [PULL 1/4] linux-user: Fix AT_PHDR when program headers are relocated into their own segment Helge Deller
@ 2026-06-18 21:54 ` Helge Deller
2026-06-18 21:54 ` [PULL 3/4] linux-user: Implement /proc/cpuinfo for m68k CPU Helge Deller
2026-06-18 21:54 ` [PULL 4/4] linux-user/xtensa: fix unlock of uninitialized frame pointer on sigreturn Helge Deller
3 siblings, 0 replies; 5+ messages in thread
From: Helge Deller @ 2026-06-18 21:54 UTC (permalink / raw)
To: qemu-devel, Stefan Hajnoczi
Cc: Pierrick Bouvier, Laurent Vivier, deller, Song Gao, Bibo Mao,
Jiaxun Yang
From: Helge Deller <deller@gmx.de>
Mimic the entries for /proc/cpuinfo to what can be seen on the debian
porterbox loomis.debian.org.
Cc: Song Gao <gaosong@loongson.cn>
Cc: Bibo Mao <maobibo@loongson.cn>
Cc: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Helge Deller <deller@gmx.de>
---
linux-user/loongarch64/elfload.c | 20 +++++++
linux-user/loongarch64/target_proc.h | 79 +++++++++++++++++++++++++++-
2 files changed, 98 insertions(+), 1 deletion(-)
diff --git a/linux-user/loongarch64/elfload.c b/linux-user/loongarch64/elfload.c
index e53957e36d..2242f20202 100644
--- a/linux-user/loongarch64/elfload.c
+++ b/linux-user/loongarch64/elfload.c
@@ -28,6 +28,26 @@ enum {
HWCAP_LOONGARCH_LBT_MIPS = (1 << 12),
};
+const char *elf_hwcap_str(uint32_t bit)
+{
+ static const char *hwcap_str[] = {
+ [__builtin_ctz(HWCAP_LOONGARCH_CPUCFG )] = "cpucfg",
+ [__builtin_ctz(HWCAP_LOONGARCH_LAM )] = "lam",
+ [__builtin_ctz(HWCAP_LOONGARCH_UAL )] = "lam_bh",
+ [__builtin_ctz(HWCAP_LOONGARCH_FPU )] = "fpu",
+ [__builtin_ctz(HWCAP_LOONGARCH_LSX )] = "lsx",
+ [__builtin_ctz(HWCAP_LOONGARCH_LASX )] = "lasx",
+ [__builtin_ctz(HWCAP_LOONGARCH_CRC32 )] = "crc32",
+ [__builtin_ctz(HWCAP_LOONGARCH_COMPLEX )] = "complex",
+ [__builtin_ctz(HWCAP_LOONGARCH_CRYPTO )] = "crypto",
+ [__builtin_ctz(HWCAP_LOONGARCH_LVZ )] = "lvz",
+ [__builtin_ctz(HWCAP_LOONGARCH_LBT_X86 )] = "lbt_x86",
+ [__builtin_ctz(HWCAP_LOONGARCH_LBT_ARM )] = "lbt_arm",
+ [__builtin_ctz(HWCAP_LOONGARCH_LBT_MIPS)] = "lbt_mips",
+ };
+
+ return bit < ARRAY_SIZE(hwcap_str) ? hwcap_str[bit] : NULL;
+}
abi_ulong get_elf_hwcap(CPUState *cs)
{
LoongArchCPU *cpu = LOONGARCH_CPU(cs);
diff --git a/linux-user/loongarch64/target_proc.h b/linux-user/loongarch64/target_proc.h
index 43fe29ca72..f739520fab 100644
--- a/linux-user/loongarch64/target_proc.h
+++ b/linux-user/loongarch64/target_proc.h
@@ -1 +1,78 @@
-/* No target-specific /proc support */
+/*
+ * Loongson specific proc functions for linux-user
+ *
+ * Copyright (c) 2026 Helge Deller
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#ifndef LOONGARCH_TARGET_PROC_H
+#define LOONGARCH_TARGET_PROC_H
+
+static int open_cpuinfo(CPUArchState *cpu_env, int fd)
+{
+ uint32_t elf_hwcap = get_elf_hwcap(env_cpu(cpu_env));
+ uint32_t prid, ser_id, pabits, vabits, i, n, num_cpus;
+ bool is_64bit = is_la64(cpu_env);
+ const char *hwcap_str;
+ struct timespec res;
+ double freq_mhz;
+
+#if TARGET_LONG_BITS == 32
+ pabits = 31;
+ vabits = 31;
+#else
+ pabits = FIELD_EX32(cpu_env->cpucfg[1], CPUCFG1, PALEN);
+ vabits = FIELD_EX32(cpu_env->cpucfg[1], CPUCFG1, VALEN);
+#endif
+
+ if (clock_getres(CLOCK_REALTIME, &res) == -1) {
+ res.tv_nsec = 1;
+ }
+ freq_mhz = 1000.0 / res.tv_nsec;
+
+ ser_id = FIELD_EX32(cpu_env->cpucfg[0], CPUCFG0, SERID);
+ prid = FIELD_EX32(cpu_env->cpucfg[0], CPUCFG0, PRID);
+
+ dprintf(fd, "system type\t\t: generic-loongson-machine\n");
+
+ num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
+ for (n = 0; n < num_cpus; n++) {
+ dprintf(fd, "\nprocessor\t\t: %d\n", n);
+ dprintf(fd, "package\t\t\t: 0\n");
+ dprintf(fd, "core\t\t\t: %d\n", n);
+ dprintf(fd, "global_id\t\t: %d\n", n);
+ dprintf(fd, "CPU Family\t\t: Loongson-%dbit\n", is_64bit ? 64 : 32);
+ dprintf(fd, "Model Name\t\t: QEMU_user-v" QEMU_VERSION "\n");
+ dprintf(fd, "PRID\t\t\t: %s (%08x)\n",
+ ser_id == PRID_SERIES_LA464 ? "LA464" :
+ ser_id == PRID_SERIES_LA132 ? "LA132" : "Unknown",
+ cpu_env->cpucfg[0]);
+ dprintf(fd, "CPU Revision\t\t: 0x%02x\n", prid);
+ dprintf(fd, "FPU Revision\t\t: 0x%02x\n",
+ FIELD_EX32(cpu_env->cpucfg[2], CPUCFG2, FP_VER));
+ dprintf(fd, "CPU MHz\t\t\t: %.2f\n", freq_mhz);
+ dprintf(fd, "Address Sizes\t\t: %d bits physical, %d bits virtual\n",
+ pabits + 1, vabits + 1);
+
+ dprintf(fd, "ISA\t\t\t:%s", " loongarch32r loongarch32s");
+ if (is_64bit) {
+ dprintf(fd, " loongarch64");
+ }
+
+ dprintf(fd, "\nFeatures\t\t:");
+ for (i = 0; i < sizeof(elf_hwcap) * 8; i++) {
+ if (!(elf_hwcap & (1 << i))) {
+ continue;
+ }
+ hwcap_str = elf_hwcap_str(i);
+ if (hwcap_str) {
+ dprintf(fd, " %s", hwcap_str);
+ }
+ }
+ dprintf(fd, "\nHardware Watchpoint\t: no\n");
+ }
+ return 0;
+}
+#define HAVE_ARCH_PROC_CPUINFO
+
+#endif /* LOONGARCH_TARGET_PROC_H */
--
2.54.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PULL 3/4] linux-user: Implement /proc/cpuinfo for m68k CPU
2026-06-18 21:54 [PULL 0/4] Linux user patches Helge Deller
2026-06-18 21:54 ` [PULL 1/4] linux-user: Fix AT_PHDR when program headers are relocated into their own segment Helge Deller
2026-06-18 21:54 ` [PULL 2/4] linux-user: Implement /proc/cpuinfo for loongarch cpus Helge Deller
@ 2026-06-18 21:54 ` Helge Deller
2026-06-18 21:54 ` [PULL 4/4] linux-user/xtensa: fix unlock of uninitialized frame pointer on sigreturn Helge Deller
3 siblings, 0 replies; 5+ messages in thread
From: Helge Deller @ 2026-06-18 21:54 UTC (permalink / raw)
To: qemu-devel, Stefan Hajnoczi
Cc: Pierrick Bouvier, Laurent Vivier, deller, Thomas Huth
From: Helge Deller <deller@gmx.de>
Mimic the entries for /proc/cpuinfo to what can be seen on the debian
porterbox mitchy.debian.org.
Cc: Thomas Huth <th.huth+qemu@posteo.eu>
Cc: Laurent Vivier <laurent@vivier.eu>
Signed-off-by: Helge Deller <deller@gmx.de>
---
linux-user/m68k/target_proc.h | 46 +++++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/linux-user/m68k/target_proc.h b/linux-user/m68k/target_proc.h
index 3df8f28e22..dca77d8483 100644
--- a/linux-user/m68k/target_proc.h
+++ b/linux-user/m68k/target_proc.h
@@ -1,6 +1,8 @@
/*
* M68K specific proc functions for linux-user
*
+ * Copyright (c) 2026 Helge Deller
+ *
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef M68K_TARGET_PROC_H
@@ -13,4 +15,48 @@ static int open_hardware(CPUArchState *cpu_env, int fd)
}
#define HAVE_ARCH_PROC_HARDWARE
+
+static int open_cpuinfo(CPUArchState *cpu_env, int fd)
+{
+ const char *cpu, *fpu;
+ struct timespec res;
+ double freq_mhz;
+
+ if (clock_getres(CLOCK_REALTIME, &res) == -1) {
+ res.tv_nsec = 1;
+ }
+ freq_mhz = 1000.0 / res.tv_nsec;
+
+ if (m68k_feature(cpu_env, M68K_FEATURE_M68010)) {
+ cpu = "68010";
+ } else if (m68k_feature(cpu_env, M68K_FEATURE_M68020)) {
+ cpu = "68020";
+ } else if (m68k_feature(cpu_env, M68K_FEATURE_M68030)) {
+ cpu = "68030";
+ } else if (m68k_feature(cpu_env, M68K_FEATURE_M68040)) {
+ cpu = "68040";
+ } else if (m68k_feature(cpu_env, M68K_FEATURE_M68060)) {
+ cpu = "68060";
+ } else {
+ cpu = "680x0";
+ }
+
+ if (m68k_feature(cpu_env, M68K_FEATURE_FPU)) {
+ fpu = cpu;
+ } else {
+ fpu = "none(soft float)";
+ }
+
+ dprintf(fd, "CPU:\t\t%s\n"
+ "MMU:\t\t%s\n"
+ "FPU:\t\t%s\n"
+ "Clocking:\t%.1fMHz\n"
+ "Model:\t\tQEMU user v" QEMU_VERSION "\n",
+ cpu, cpu, fpu, freq_mhz);
+ /* dropped BogoMips and Calibration for now */
+
+ return 0;
+}
+#define HAVE_ARCH_PROC_CPUINFO
+
#endif /* M68K_TARGET_PROC_H */
--
2.54.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PULL 4/4] linux-user/xtensa: fix unlock of uninitialized frame pointer on sigreturn
2026-06-18 21:54 [PULL 0/4] Linux user patches Helge Deller
` (2 preceding siblings ...)
2026-06-18 21:54 ` [PULL 3/4] linux-user: Implement /proc/cpuinfo for m68k CPU Helge Deller
@ 2026-06-18 21:54 ` Helge Deller
3 siblings, 0 replies; 5+ messages in thread
From: Helge Deller @ 2026-06-18 21:54 UTC (permalink / raw)
To: qemu-devel, Stefan Hajnoczi
Cc: Pierrick Bouvier, Laurent Vivier, deller, Matt Turner,
qemu-stable
From: Matt Turner <mattst88@gmail.com>
If lock_user_struct fails, frame is uninitialized but the badframe
label unconditionally calls unlock_user_struct on it. Handle the
lock failure inline so badframe is only reached with a valid lock.
Signed-off-by: Matt Turner <mattst88@gmail.com>
Cc: qemu-stable@nongnu.org
Reviewed-by: Helge Deller <deller@gmx.de>
Signed-off-by: Helge Deller <deller@gmx.de>
---
linux-user/xtensa/signal.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/linux-user/xtensa/signal.c b/linux-user/xtensa/signal.c
index e3f9da322b..4990c50045 100644
--- a/linux-user/xtensa/signal.c
+++ b/linux-user/xtensa/signal.c
@@ -355,7 +355,8 @@ long do_rt_sigreturn(CPUXtensaState *env)
trace_user_do_rt_sigreturn(env, frame_addr);
if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
- goto badframe;
+ force_sig(TARGET_SIGSEGV);
+ return -QEMU_ESIGRETURN;
}
target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
set_sigmask(&set);
--
2.54.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-06-18 21:55 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-18 21:54 [PULL 0/4] Linux user patches Helge Deller
2026-06-18 21:54 ` [PULL 1/4] linux-user: Fix AT_PHDR when program headers are relocated into their own segment Helge Deller
2026-06-18 21:54 ` [PULL 2/4] linux-user: Implement /proc/cpuinfo for loongarch cpus Helge Deller
2026-06-18 21:54 ` [PULL 3/4] linux-user: Implement /proc/cpuinfo for m68k CPU Helge Deller
2026-06-18 21:54 ` [PULL 4/4] linux-user/xtensa: fix unlock of uninitialized frame pointer on sigreturn Helge Deller
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.