Skip to content

Commit 5298b7c

Browse files
benzearichardweinberger
authored andcommitted
um: add back support for FXSAVE registers
It was reported that qemu may not enable the XSTATE CPU extension, which is a requirement after commit 3f17fed ("um: switch to regset API and depend on XSTATE"). Add a fallback to use FXSAVE (FP registers on x86_64 and XFP on i386) which is just a shorter version of the same data. The only difference is that the XSTATE magic should not be set in the signal frame. Note that this still drops support for the older i386 FP register layout as supporting this would require more backward compatibility to build a correct signal frame. Fixes: 3f17fed ("um: switch to regset API and depend on XSTATE") Reported-by: SeongJae Park <[email protected]> Closes: https://lore.kernel.org/r/[email protected] Tested-by: SeongJae Park <[email protected]> Signed-off-by: Benjamin Berg <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Johannes Berg <[email protected]> Signed-off-by: Richard Weinberger <[email protected]>
1 parent a64dcfb commit 5298b7c

File tree

2 files changed

+23
-3
lines changed

2 files changed

+23
-3
lines changed

arch/x86/um/os-Linux/registers.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <registers.h>
1919
#include <sys/mman.h>
2020

21+
static unsigned long ptrace_regset;
2122
unsigned long host_fp_size;
2223

2324
int get_fp_registers(int pid, unsigned long *regs)
@@ -27,7 +28,7 @@ int get_fp_registers(int pid, unsigned long *regs)
2728
.iov_len = host_fp_size,
2829
};
2930

30-
if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
31+
if (ptrace(PTRACE_GETREGSET, pid, ptrace_regset, &iov) < 0)
3132
return -errno;
3233
return 0;
3334
}
@@ -39,7 +40,7 @@ int put_fp_registers(int pid, unsigned long *regs)
3940
.iov_len = host_fp_size,
4041
};
4142

42-
if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
43+
if (ptrace(PTRACE_SETREGSET, pid, ptrace_regset, &iov) < 0)
4344
return -errno;
4445
return 0;
4546
}
@@ -58,9 +59,23 @@ int arch_init_registers(int pid)
5859
return -ENOMEM;
5960

6061
/* GDB has x86_xsave_length, which uses x86_cpuid_count */
61-
ret = ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov);
62+
ptrace_regset = NT_X86_XSTATE;
63+
ret = ptrace(PTRACE_GETREGSET, pid, ptrace_regset, &iov);
6264
if (ret)
6365
ret = -errno;
66+
67+
if (ret == -ENODEV) {
68+
#ifdef CONFIG_X86_32
69+
ptrace_regset = NT_PRXFPREG;
70+
#else
71+
ptrace_regset = NT_PRFPREG;
72+
#endif
73+
iov.iov_len = 2 * 1024 * 1024;
74+
ret = ptrace(PTRACE_GETREGSET, pid, ptrace_regset, &iov);
75+
if (ret)
76+
ret = -errno;
77+
}
78+
6479
munmap(iov.iov_base, 2 * 1024 * 1024);
6580

6681
host_fp_size = iov.iov_len;

arch/x86/um/signal.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,12 @@ static int copy_sc_to_user(struct sigcontext __user *to,
187187
* Put magic/size values for userspace. We do not bother to verify them
188188
* later on, however, userspace needs them should it try to read the
189189
* XSTATE data. And ptrace does not fill in these parts.
190+
*
191+
* Skip this if we do not have an XSTATE frame.
190192
*/
193+
if (host_fp_size <= sizeof(to_fp64->fpstate))
194+
return 0;
195+
191196
BUILD_BUG_ON(sizeof(int) != FP_XSTATE_MAGIC2_SIZE);
192197
#ifdef CONFIG_X86_32
193198
__put_user(offsetof(struct _fpstate_32, _fxsr_env) +

0 commit comments

Comments
 (0)