[CRIU] [PATCH 43/44] FPU: introduced the support for multiple FPU architectures.
Alexander Kartashov
alekskartashov at parallels.com
Mon Jan 7 10:05:12 EST 2013
* The routine sigreturn_prep_xsave_frame() is renamed to sigreturn_prep_fpu_frame().
* Moved the routines sigreturn_prep_fpu_frame(), show_rt_xsave_frame(), and
valid_xsave_frame() to the file crtools.c.
* Introduced the structure fpu_state_t to pass the FPU state to the restorer
in a machine-independent way.
Signed-off-by: Alexander Kartashov <alekskartashov at parallels.com>
---
arch/x86/crtools.c | 128 +++++++++++++++++++++++++++++++++++++++
arch/x86/include/asm/restore.h | 3 +
arch/x86/include/asm/types.h | 15 +++++
arch/x86/restorer.c | 4 +-
cr-restore.c | 129 +---------------------------------------
include/restorer.h | 9 +--
6 files changed, 150 insertions(+), 138 deletions(-)
diff --git a/arch/x86/crtools.c b/arch/x86/crtools.c
index 58c4820..2932774 100644
--- a/arch/x86/crtools.c
+++ b/arch/x86/crtools.c
@@ -16,6 +16,7 @@
#include "fpu.h"
#include "elf.h"
#include "parasite-syscall.h"
+#include "restorer.h"
/*
@@ -284,3 +285,130 @@ void core_entry_free(CoreEntry *core)
xfree(core->ids);
}
}
+
+static bool valid_xsave_frame(CoreEntry *core)
+{
+ struct xsave_struct *x = NULL;
+
+ if (core->thread_info->fpregs->n_st_space < ARRAY_SIZE(x->i387.st_space)) {
+ pr_err("Corruption in FPU st_space area "
+ "(got %li but %li expected)\n",
+ (long)core->thread_info->fpregs->n_st_space,
+ (long)ARRAY_SIZE(x->i387.st_space));
+ return false;
+ }
+
+ if (core->thread_info->fpregs->n_xmm_space < ARRAY_SIZE(x->i387.xmm_space)) {
+ pr_err("Corruption in FPU xmm_space area "
+ "(got %li but %li expected)\n",
+ (long)core->thread_info->fpregs->n_st_space,
+ (long)ARRAY_SIZE(x->i387.xmm_space));
+ return false;
+ }
+
+ if (cpu_has_feature(X86_FEATURE_XSAVE)) {
+ if (!core->thread_info->fpregs->xsave) {
+ pr_err("FPU xsave area is missing, "
+ "but host cpu requires it\n");
+ return false;
+ }
+ if (core->thread_info->fpregs->xsave->n_ymmh_space < ARRAY_SIZE(x->ymmh.ymmh_space)) {
+ pr_err("Corruption in FPU ymmh_space area "
+ "(got %li but %li expected)\n",
+ (long)core->thread_info->fpregs->xsave->n_ymmh_space,
+ (long)ARRAY_SIZE(x->ymmh.ymmh_space));
+ return false;
+ }
+ } else {
+ if (core->thread_info->fpregs->xsave) {
+ pr_err("FPU xsave area present, "
+ "but host cpu doesn't support it\n");
+ return false;
+ }
+ return true;
+ }
+
+ return true;
+}
+
+static void show_rt_xsave_frame(struct xsave_struct *x)
+{
+ struct fpx_sw_bytes *fpx = (void *)&x->i387.sw_reserved;
+ struct xsave_hdr_struct *xsave_hdr = &x->xsave_hdr;
+ struct i387_fxsave_struct *i387 = &x->i387;
+
+ pr_debug("xsave runtime structure\n");
+ pr_debug("-----------------------\n");
+
+ pr_debug("cwd:%x swd:%x twd:%x fop:%x mxcsr:%x mxcsr_mask:%x\n",
+ (int)i387->cwd, (int)i387->swd, (int)i387->twd,
+ (int)i387->fop, (int)i387->mxcsr, (int)i387->mxcsr_mask);
+
+ pr_debug("magic1:%x extended_size:%x xstate_bv:%lx xstate_size:%x\n",
+ fpx->magic1, fpx->extended_size, P(fpx->xstate_bv), fpx->xstate_size);
+
+ pr_debug("xstate_bv: %lx\n", P(xsave_hdr->xstate_bv));
+
+ pr_debug("-----------------------\n");
+}
+
+int sigreturn_prep_fpu_frame(struct thread_restore_args *args, CoreEntry *core)
+{
+ struct xsave_struct *x = &args->fpu_state.xsave;
+
+ /*
+ * If no FPU information provided -- we're restoring
+ * old image which has no FPU support, or the dump simply
+ * has no FPU support at all.
+ */
+ if (!core->thread_info->fpregs) {
+ args->has_fpu = false;
+ return 0;
+ }
+
+ if (!valid_xsave_frame(core))
+ return -1;
+
+ args->has_fpu = true;
+
+#define assign_reg(dst, src, e) do { dst.e = (__typeof__(dst.e))src->e; } while (0)
+#define assign_array(dst, src, e) memcpy(dst.e, (src)->e, sizeof(dst.e))
+
+ assign_reg(x->i387, core->thread_info->fpregs, cwd);
+ assign_reg(x->i387, core->thread_info->fpregs, swd);
+ assign_reg(x->i387, core->thread_info->fpregs, twd);
+ assign_reg(x->i387, core->thread_info->fpregs, fop);
+ assign_reg(x->i387, core->thread_info->fpregs, rip);
+ assign_reg(x->i387, core->thread_info->fpregs, rdp);
+ assign_reg(x->i387, core->thread_info->fpregs, mxcsr);
+ assign_reg(x->i387, core->thread_info->fpregs, mxcsr_mask);
+
+ assign_array(x->i387, core->thread_info->fpregs, st_space);
+ assign_array(x->i387, core->thread_info->fpregs, xmm_space);
+
+ if (cpu_has_feature(X86_FEATURE_XSAVE)) {
+ struct fpx_sw_bytes *fpx_sw = (void *)&x->i387.sw_reserved;
+ void *magic2;
+
+ x->xsave_hdr.xstate_bv = XSTATE_FP | XSTATE_SSE | XSTATE_YMM;
+ assign_array(x->ymmh, core->thread_info->fpregs->xsave, ymmh_space);
+
+ fpx_sw->magic1 = FP_XSTATE_MAGIC1;
+ fpx_sw->xstate_bv = XSTATE_FP | XSTATE_SSE | XSTATE_YMM;
+ fpx_sw->xstate_size = sizeof(struct xsave_struct);
+ fpx_sw->extended_size = sizeof(struct xsave_struct) + FP_XSTATE_MAGIC2_SIZE;
+
+ /*
+ * This should be at the end of xsave frame.
+ */
+ magic2 = args->fpu_state.__pad + sizeof(struct xsave_struct);
+ *(u32 *)magic2 = FP_XSTATE_MAGIC2;
+ }
+
+ show_rt_xsave_frame(x);
+
+#undef assign_reg
+#undef assign_array
+
+ return 0;
+}
diff --git a/arch/x86/include/asm/restore.h b/arch/x86/include/asm/restore.h
index 62faffa..5e2f88f 100644
--- a/arch/x86/include/asm/restore.h
+++ b/arch/x86/include/asm/restore.h
@@ -17,4 +17,7 @@
#define core_get_tls(pcore, ptls)
+
+int sigreturn_prep_fpu_frame(struct thread_restore_args *args, CoreEntry *core);
+
#endif
diff --git a/arch/x86/include/asm/types.h b/arch/x86/include/asm/types.h
index 468ac23..b90eb1a 100644
--- a/arch/x86/include/asm/types.h
+++ b/arch/x86/include/asm/types.h
@@ -262,4 +262,19 @@ typedef uint64_t auxv_t;
#define P(i) i
+
+#include "fpu.h"
+
+typedef struct {
+ /*
+ * The FPU xsave area must be continious and FP_MIN_ALIGN_BYTES
+ * aligned, thus make sure the compiler won't insert any hole here.
+ */
+
+ union {
+ struct xsave_struct xsave;
+ unsigned char __pad[sizeof(struct xsave_struct) + FP_XSTATE_MAGIC2_SIZE];
+ };
+} fpu_state_t;
+
#endif /* __CR_ASM_TYPES_H__ */
diff --git a/arch/x86/restorer.c b/arch/x86/restorer.c
index df42c27..daff30a 100644
--- a/arch/x86/restorer.c
+++ b/arch/x86/restorer.c
@@ -58,10 +58,10 @@ int restore_gpregs(struct rt_sigframe *f, UserX86RegsEntry *r)
int restore_fpu(struct rt_sigframe *sigframe, struct thread_restore_args *args)
{
if (args->has_fpu) {
- unsigned long addr = (unsigned long)(void *)&args->xsave;
+ unsigned long addr = (unsigned long)(void *)&args->fpu_state.xsave;
if ((addr % 64ul) == 0ul) {
- sigframe->uc.uc_mcontext.fpstate = &args->xsave;
+ sigframe->uc.uc_mcontext.fpstate = &args->fpu_state.xsave;
} else {
pr_err("Unaligned address passed: %lx\n", addr);
return -1;
diff --git a/cr-restore.c b/cr-restore.c
index cc944fb..95b48b3 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -1581,133 +1581,6 @@ static int prep_sched_info(struct rst_sched_param *sp, ThreadCoreEntry *tc)
return 0;
}
-static bool valid_xsave_frame(CoreEntry *core)
-{
- struct xsave_struct *x = NULL;
-
- if (core->thread_info->fpregs->n_st_space < ARRAY_SIZE(x->i387.st_space)) {
- pr_err("Corruption in FPU st_space area "
- "(got %li but %li expected)\n",
- (long)core->thread_info->fpregs->n_st_space,
- (long)ARRAY_SIZE(x->i387.st_space));
- return false;
- }
-
- if (core->thread_info->fpregs->n_xmm_space < ARRAY_SIZE(x->i387.xmm_space)) {
- pr_err("Corruption in FPU xmm_space area "
- "(got %li but %li expected)\n",
- (long)core->thread_info->fpregs->n_st_space,
- (long)ARRAY_SIZE(x->i387.xmm_space));
- return false;
- }
-
- if (cpu_has_feature(X86_FEATURE_XSAVE)) {
- if (!core->thread_info->fpregs->xsave) {
- pr_err("FPU xsave area is missing, "
- "but host cpu requires it\n");
- return false;
- }
- if (core->thread_info->fpregs->xsave->n_ymmh_space < ARRAY_SIZE(x->ymmh.ymmh_space)) {
- pr_err("Corruption in FPU ymmh_space area "
- "(got %li but %li expected)\n",
- (long)core->thread_info->fpregs->xsave->n_ymmh_space,
- (long)ARRAY_SIZE(x->ymmh.ymmh_space));
- return false;
- }
- } else {
- if (core->thread_info->fpregs->xsave) {
- pr_err("FPU xsave area present, "
- "but host cpu doesn't support it\n");
- return false;
- }
- return true;
- }
-
- return true;
-}
-
-static void show_rt_xsave_frame(struct xsave_struct *x)
-{
- struct fpx_sw_bytes *fpx = (void *)&x->i387.sw_reserved;
- struct xsave_hdr_struct *xsave_hdr = &x->xsave_hdr;
- struct i387_fxsave_struct *i387 = &x->i387;
-
- pr_debug("xsave runtime structure\n");
- pr_debug("-----------------------\n");
-
- pr_debug("cwd:%x swd:%x twd:%x fop:%x mxcsr:%x mxcsr_mask:%x\n",
- (int)i387->cwd, (int)i387->swd, (int)i387->twd,
- (int)i387->fop, (int)i387->mxcsr, (int)i387->mxcsr_mask);
-
- pr_debug("magic1:%x extended_size:%x xstate_bv:%lx xstate_size:%x\n",
- fpx->magic1, fpx->extended_size, P(fpx->xstate_bv), fpx->xstate_size);
-
- pr_debug("xstate_bv: %lx\n", P(xsave_hdr->xstate_bv));
-
- pr_debug("-----------------------\n");
-}
-
-static int sigreturn_prep_xsave_frame(struct thread_restore_args *args, CoreEntry *core)
-{
- struct xsave_struct *x = &args->xsave;
-
- /*
- * If no FPU information provided -- we're restoring
- * old image which has no FPU support, or the dump simply
- * has no FPU support at all.
- */
- if (!core->thread_info->fpregs) {
- args->has_fpu = false;
- return 0;
- }
-
- if (!valid_xsave_frame(core))
- return -1;
-
- args->has_fpu = true;
-
-#define assign_reg(dst, src, e) do { dst.e = (__typeof__(dst.e))src->e; } while (0)
-#define assign_array(dst, src, e) memcpy(dst.e, (src)->e, sizeof(dst.e))
-
- assign_reg(x->i387, core->thread_info->fpregs, cwd);
- assign_reg(x->i387, core->thread_info->fpregs, swd);
- assign_reg(x->i387, core->thread_info->fpregs, twd);
- assign_reg(x->i387, core->thread_info->fpregs, fop);
- assign_reg(x->i387, core->thread_info->fpregs, rip);
- assign_reg(x->i387, core->thread_info->fpregs, rdp);
- assign_reg(x->i387, core->thread_info->fpregs, mxcsr);
- assign_reg(x->i387, core->thread_info->fpregs, mxcsr_mask);
-
- assign_array(x->i387, core->thread_info->fpregs, st_space);
- assign_array(x->i387, core->thread_info->fpregs, xmm_space);
-
- if (cpu_has_feature(X86_FEATURE_XSAVE)) {
- struct fpx_sw_bytes *fpx_sw = (void *)&x->i387.sw_reserved;
- void *magic2;
-
- x->xsave_hdr.xstate_bv = XSTATE_FP | XSTATE_SSE | XSTATE_YMM;
- assign_array(x->ymmh, core->thread_info->fpregs->xsave, ymmh_space);
-
- fpx_sw->magic1 = FP_XSTATE_MAGIC1;
- fpx_sw->xstate_bv = XSTATE_FP | XSTATE_SSE | XSTATE_YMM;
- fpx_sw->xstate_size = sizeof(struct xsave_struct);
- fpx_sw->extended_size = sizeof(struct xsave_struct) + FP_XSTATE_MAGIC2_SIZE;
-
- /*
- * This should be at the end of xsave frame.
- */
- magic2 = args->__pad + sizeof(struct xsave_struct);
- *(u32 *)magic2 = FP_XSTATE_MAGIC2;
- }
-
- show_rt_xsave_frame(x);
-
-#undef assign_reg
-#undef assign_array
-
- return 0;
-}
-
extern void __gcov_flush(void) __attribute__((weak));
void __gcov_flush(void) {}
@@ -1924,7 +1797,7 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core)
goto err;
}
- if (sigreturn_prep_xsave_frame(&thread_args[i], core))
+ if (sigreturn_prep_fpu_frame(&thread_args[i], core))
goto err;
if (thread_args[i].pid != pid)
diff --git a/include/restorer.h b/include/restorer.h
index e6f6c6e..b0c2600 100644
--- a/include/restorer.h
+++ b/include/restorer.h
@@ -77,15 +77,8 @@ struct thread_restore_args {
struct task_restore_core_args *ta;
- /*
- * The FPU xsave area must be continious and FP_MIN_ALIGN_BYTES
- * aligned, thus make sure the compiler won't insert any hole here.
- */
bool has_fpu;
- union {
- struct xsave_struct xsave;
- unsigned char __pad[sizeof(struct xsave_struct) + FP_XSTATE_MAGIC2_SIZE];
- };
+ fpu_state_t fpu_state;
u32 tls;
} __aligned(sizeof(long));
--
1.7.10.4
More information about the CRIU
mailing list