[5/6] compel: Extend FPU structures to support ia32 mode

Submitted by Cyrill Gorcunov on Feb. 13, 2017, 3:03 p.m.

Details

Message ID 1486998203-2834-6-git-send-email-gorcunov@openvz.org
State New
Series "ia32: Add support for FPU c/r in compat environment"
Headers show

Commit Message

Cyrill Gorcunov Feb. 13, 2017, 3:03 p.m.
Because it touches base types need to update criu
code accordingly.

Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
---
 compel/arch/x86/src/lib/include/uapi/asm/fpu.h | 37 +++++++++++++++++++++++---
 compel/arch/x86/src/lib/infect.c               | 12 ++++++---
 criu/arch/x86/crtools.c                        |  8 ++++--
 criu/arch/x86/sigframe.c                       |  6 ++---
 4 files changed, 50 insertions(+), 13 deletions(-)

Patch hide | download patch | download mbox

diff --git a/compel/arch/x86/src/lib/include/uapi/asm/fpu.h b/compel/arch/x86/src/lib/include/uapi/asm/fpu.h
index d3245f256924..ee6e81bcd9d8 100644
--- a/compel/arch/x86/src/lib/include/uapi/asm/fpu.h
+++ b/compel/arch/x86/src/lib/include/uapi/asm/fpu.h
@@ -88,14 +88,43 @@  struct xsave_struct {
  * This one is used in restorer.
  */
 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;
+		uint8_t			__pad[sizeof(struct xsave_struct) + FP_XSTATE_MAGIC2_SIZE];
+	};
+} fpu_state_64_t;
+
+struct user_i387_ia32_struct {
+	uint32_t			cwd;		/* FPU Control Word		*/
+	uint32_t			swd;		/* FPU Status Word		*/
+	uint32_t			twd;		/* FPU Tag Word			*/
+	uint32_t			fip;		/* FPU IP Offset		*/
+	uint32_t			fcs;		/* FPU IP Selector		*/
+	uint32_t			foo;		/* FPU Operand Pointer Offset	*/
+	uint32_t			fos;		/* FPU Operand Pointer Selector	*/
+	uint32_t			st_space[20];   /* 8*10 bytes for each FP-reg = 80 bytes */
+} __packed;
+
+typedef struct {
+	struct {
+		struct user_i387_ia32_struct	i387_ia32;
 
+		/* Software status information [not touched by FSAVE]:		*/
+		uint32_t			status;
+	} __packed fregs_state;
 	union {
 		struct xsave_struct	xsave;
 		uint8_t			__pad[sizeof(struct xsave_struct) + FP_XSTATE_MAGIC2_SIZE];
+	} __packed;
+}  __packed fpu_state_ia32_t;
+
+/*
+ * This one is used in restorer.
+ */
+typedef struct {
+	union {
+		fpu_state_64_t			fpu_state_64;
+		fpu_state_ia32_t		fpu_state_ia32;
 	};
 
 	uint8_t has_fpu;
diff --git a/compel/arch/x86/src/lib/infect.c b/compel/arch/x86/src/lib/infect.c
index d5b4f7659c65..43b080000fe3 100644
--- a/compel/arch/x86/src/lib/infect.c
+++ b/compel/arch/x86/src/lib/infect.c
@@ -102,7 +102,11 @@  int sigreturn_prep_regs_plain(struct rt_sigframe *sigframe,
 	}
 
 	fpu_state->has_fpu = true;
-	memcpy(&fpu_state->xsave, fpregs, sizeof(*fpregs));
+	if (is_native) {
+		memcpy(&fpu_state->fpu_state_64.xsave, fpregs, sizeof(*fpregs));
+	} else {
+		memcpy(&fpu_state->fpu_state_ia32.xsave, fpregs, sizeof(*fpregs));
+	}
 
 	return 0;
 }
@@ -113,12 +117,12 @@  int sigreturn_prep_fpu_frame_plain(struct rt_sigframe *sigframe,
 	fpu_state_t *fpu_state = (sigframe->is_native) ?
 		&rsigframe->native.fpu_state :
 		&rsigframe->compat.fpu_state;
-	unsigned long addr = (unsigned long)(void *)&fpu_state->xsave;
 
 	if (sigframe->is_native)
-		sigframe->native.uc.uc_mcontext.fpstate = &fpu_state->xsave;
+		sigframe->native.uc.uc_mcontext.fpstate = &fpu_state->fpu_state_64.xsave;
 	else if (!sigframe->is_native)
-		sigframe->compat.uc.uc_mcontext.fpstate = (uint32_t)addr;
+		sigframe->compat.uc.uc_mcontext.fpstate =
+			(uint32_t)(long)(void *)&fpu_state->fpu_state_ia32;
 
 	return 0;
 }
diff --git a/criu/arch/x86/crtools.c b/criu/arch/x86/crtools.c
index 33f4048704ff..0986055d53fa 100644
--- a/criu/arch/x86/crtools.c
+++ b/criu/arch/x86/crtools.c
@@ -303,7 +303,9 @@  int restore_fpu(struct rt_sigframe *sigframe, CoreEntry *core)
 	fpu_state_t *fpu_state = core_is_compat(core) ?
 		&sigframe->compat.fpu_state :
 		&sigframe->native.fpu_state;
-	struct xsave_struct *x = &fpu_state->xsave;
+	struct xsave_struct *x = core_is_compat(core) ?
+		&fpu_state->fpu_state_ia32.xsave :
+		&fpu_state->fpu_state_64.xsave;
 
 	/*
 	 * If no FPU information provided -- we're restoring
@@ -356,7 +358,9 @@  int restore_fpu(struct rt_sigframe *sigframe, CoreEntry *core)
 		/*
 		 * This should be at the end of xsave frame.
 		 */
-		magic2 = fpu_state->__pad + sizeof(struct xsave_struct);
+		magic2 = (core_is_compat(core) ?
+			  fpu_state->fpu_state_ia32.__pad :
+			  fpu_state->fpu_state_64.__pad) + sizeof(struct xsave_struct);
 		*(u32 *)magic2 = FP_XSTATE_MAGIC2;
 	}
 
diff --git a/criu/arch/x86/sigframe.c b/criu/arch/x86/sigframe.c
index 24afb863f0b5..efe33c4c0512 100644
--- a/criu/arch/x86/sigframe.c
+++ b/criu/arch/x86/sigframe.c
@@ -16,12 +16,12 @@  int sigreturn_prep_fpu_frame(struct rt_sigframe *sigframe,
 	fpu_state_t *fpu_state = (sigframe->is_native) ?
 		&rsigframe->native.fpu_state :
 		&rsigframe->compat.fpu_state;
-	unsigned long addr = (unsigned long)(void *)&fpu_state->xsave;
 
 	if (sigframe->is_native)
-		sigframe->native.uc.uc_mcontext.fpstate = &fpu_state->xsave;
+		sigframe->native.uc.uc_mcontext.fpstate = &fpu_state->fpu_state_64.xsave;
 	else if (!sigframe->is_native)
-		sigframe->compat.uc.uc_mcontext.fpstate = (uint32_t)addr;
+		sigframe->compat.uc.uc_mcontext.fpstate =
+			(uint32_t)(long)(void *)&fpu_state->fpu_state_ia32;
 
 	return 0;
 }