On Tue, 2024-12-03 at 07:56 -0800, SeongJae Park wrote: > On Tue, 03 Dec 2024 07:01:09 SeongJae Park <s...@kernel.org> wrote: > > > On Tue, 03 Dec 2024 09:40:34 +0100 Benjamin Berg > > <benja...@sipsolutions.net> wrote: > > > > > Hi, > > > > > > that probably means the size detection for the FPU state (i.e. > > > PTRACE_GETREGSET for NT_X86_XSTATE is incorrect on a 32bit host > > > in some > > > way. > > > > > > Is there anything special about the qemu setup or it is just a > > > default > > > qemu-x86? > > > > I use default qemu-system-x86_64 on my system. > > > > $ qemu-system-x86_64 --version > > QEMU emulator version 8.2.2 (qemu-8.2.2-1.1.hs+fb.el9) > > Copyright (c) 2003-2023 Fabrice Bellard and the QEMU Project > > developers > > > > I forgot saying it is not just x86 but x86_64, sorry. > > Oh, and seems my qemu has some downstream changes. I will try to reproduce > the > issue with upstream versions and report the result again.
I doubt that is the reason. The code tries to detect the size of the NT_X86_XSTATE register set and something breaks. Thinking about it a bit, the only good explanation is that the qemu CPU does not have XSTATE support. This would cause the ptrace syscall to fetch the NT_X86_XSTATE register set to always fail (with -ENODEV). Honestly, I just had not expected such an issue. Could you try the below patch to add a fallback? Regards, Benjamin diff --git a/arch/x86/um/os-Linux/registers.c b/arch/x86/um/os-Linux/registers.c index 76eaeb93928c..eb1cdadc8a61 100644 --- a/arch/x86/um/os-Linux/registers.c +++ b/arch/x86/um/os-Linux/registers.c @@ -18,6 +18,7 @@ #include <registers.h> #include <sys/mman.h> +static unsigned long ptrace_regset; unsigned long host_fp_size; int get_fp_registers(int pid, unsigned long *regs) @@ -27,7 +28,7 @@ int get_fp_registers(int pid, unsigned long *regs) .iov_len = host_fp_size, }; - if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0) + if (ptrace(PTRACE_GETREGSET, pid, ptrace_regset, &iov) < 0) return -errno; return 0; } @@ -39,7 +40,7 @@ int put_fp_registers(int pid, unsigned long *regs) .iov_len = host_fp_size, }; - if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0) + if (ptrace(PTRACE_SETREGSET, pid, ptrace_regset, &iov) < 0) return -errno; return 0; } @@ -58,9 +59,23 @@ int arch_init_registers(int pid) return -ENOMEM; /* GDB has x86_xsave_length, which uses x86_cpuid_count */ - ret = ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov); + ptrace_regset = NT_X86_XSTATE; + ret = ptrace(PTRACE_GETREGSET, pid, ptrace_regset, &iov); if (ret) ret = -errno; + + if (ret == -ENODEV) { +#ifdef CONFIG_X86_32 + ptrace_regset = NT_PRXFPREG; +#else + ptrace_regset = NT_PRFPREG; +#endif + iov.iov_len = 2 * 1024 * 1024; + ret = ptrace(PTRACE_GETREGSET, pid, ptrace_regset, &iov); + if (ret) + ret = -errno; + } + munmap(iov.iov_base, 2 * 1024 * 1024); host_fp_size = iov.iov_len;