[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