mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-30 22:05:36 +00:00
Fill FPU init state if it's not provided by kernel.
Apparently Skylake uses init-optimization when saving FPU state, and ptrace() returns XSTATE_BV[0] = 0 meaning FPU was not used by a task (in init state). Since CRIU restore uses sigreturn to restore registers, FPU state is always restored. Fill the state with default values on dump to make restore happy. Signed-off-by: Michał Mirosław <emmir@google.com>
This commit is contained in:
committed by
Andrei Vagin
parent
c75c017e4c
commit
c6ee1ba05e
@@ -220,6 +220,16 @@ int sigreturn_prep_fpu_frame_plain(struct rt_sigframe *sigframe, struct rt_sigfr
|
||||
#define get_signed_user_reg(pregs, name) \
|
||||
((user_regs_native(pregs)) ? (int64_t)((pregs)->native.name) : (int32_t)((pregs)->compat.name))
|
||||
|
||||
static int get_task_fpregs(pid_t pid, user_fpregs_struct_t *xsave)
|
||||
{
|
||||
if (ptrace(PTRACE_GETFPREGS, pid, NULL, xsave)) {
|
||||
pr_perror("Can't obtain FPU registers for %d", pid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_task_xsave(pid_t pid, user_fpregs_struct_t *xsave)
|
||||
{
|
||||
struct iovec iov;
|
||||
@@ -232,14 +242,15 @@ static int get_task_xsave(pid_t pid, user_fpregs_struct_t *xsave)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_task_fpregs(pid_t pid, user_fpregs_struct_t *xsave)
|
||||
{
|
||||
if (ptrace(PTRACE_GETFPREGS, pid, NULL, xsave)) {
|
||||
pr_perror("Can't obtain FPU registers for %d", pid);
|
||||
return -1;
|
||||
if ((xsave->xsave_hdr.xstate_bv & 3) != 3) {
|
||||
// Due to init-optimisation [1] x87 FPU or SSE state may not be filled in.
|
||||
// Since those are restored unconditionally, make sure the init values are
|
||||
// filled by retrying with old PTRACE_GETFPREGS.
|
||||
//
|
||||
// [1] Intel® 64 and IA-32 Architectures Software Developer's
|
||||
// Manual Volume 1: Basic Architecture
|
||||
// Section 13.6: Processor tracking of XSAVE-managed state
|
||||
return get_task_fpregs(pid, xsave);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
Reference in New Issue
Block a user