From cdaabbd74b15296acf09215355a7f3b07b92b83e Mon Sep 17 00:00:00 2001
From: Russell King <rmk@dyn-67.arm.linux.org.uk>
Date: Sun, 12 Mar 2006 22:36:06 +0000
Subject: [PATCH] [ARM] iwmmxt thread state alignment

This patch removes the reliance of iwmmxt on hand coded alignments.
Since thread_info is always 8K aligned, specifying that fpstate is
8-byte aligned achieves the same effect without needing to resort
to hand coded alignments.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 arch/arm/kernel/asm-offsets.c |  4 +++-
 arch/arm/kernel/ptrace.c      | 14 ++++----------
 include/asm-arm/fpstate.h     |  4 +++-
 include/asm-arm/thread_info.h |  2 +-
 4 files changed, 11 insertions(+), 13 deletions(-)

diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 0abbce8c70b..b324dcac1c5 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -57,7 +57,9 @@ int main(void)
   DEFINE(TI_TP_VALUE,		offsetof(struct thread_info, tp_value));
   DEFINE(TI_FPSTATE,		offsetof(struct thread_info, fpstate));
   DEFINE(TI_VFPSTATE,		offsetof(struct thread_info, vfpstate));
-  DEFINE(TI_IWMMXT_STATE,	(offsetof(struct thread_info, fpstate)+4)&~7);
+#ifdef CONFIG_IWMMXT
+  DEFINE(TI_IWMMXT_STATE,	offsetof(struct thread_info, fpstate.iwmmxt));
+#endif
   BLANK();
   DEFINE(S_R0,			offsetof(struct pt_regs, ARM_r0));
   DEFINE(S_R1,			offsetof(struct pt_regs, ARM_r1));
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 7b6256bb590..bc9e2f8ae32 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -610,15 +610,12 @@ static int ptrace_setfpregs(struct task_struct *tsk, void __user *ufp)
 static int ptrace_getwmmxregs(struct task_struct *tsk, void __user *ufp)
 {
 	struct thread_info *thread = task_thread_info(tsk);
-	void *ptr = &thread->fpstate;
 
 	if (!test_ti_thread_flag(thread, TIF_USING_IWMMXT))
 		return -ENODATA;
 	iwmmxt_task_disable(thread);  /* force it to ram */
-	/* The iWMMXt state is stored doubleword-aligned.  */
-	if (((long) ptr) & 4)
-		ptr += 4;
-	return copy_to_user(ufp, ptr, 0x98) ? -EFAULT : 0;
+	return copy_to_user(ufp, &thread->fpstate.iwmmxt, IWMMXT_SIZE)
+		? -EFAULT : 0;
 }
 
 /*
@@ -627,15 +624,12 @@ static int ptrace_getwmmxregs(struct task_struct *tsk, void __user *ufp)
 static int ptrace_setwmmxregs(struct task_struct *tsk, void __user *ufp)
 {
 	struct thread_info *thread = task_thread_info(tsk);
-	void *ptr = &thread->fpstate;
 
 	if (!test_ti_thread_flag(thread, TIF_USING_IWMMXT))
 		return -EACCES;
 	iwmmxt_task_release(thread);  /* force a reload */
-	/* The iWMMXt state is stored doubleword-aligned.  */
-	if (((long) ptr) & 4)
-		ptr += 4;
-	return copy_from_user(ptr, ufp, 0x98) ? -EFAULT : 0;
+	return copy_from_user(&thead->fpstate.iwmmxt, ufp, IWMMXT_SIZE)
+		? -EFAULT : 0;
 }
 
 #endif
diff --git a/include/asm-arm/fpstate.h b/include/asm-arm/fpstate.h
index f7430e3aa55..6246bf83627 100644
--- a/include/asm-arm/fpstate.h
+++ b/include/asm-arm/fpstate.h
@@ -55,8 +55,10 @@ struct fp_soft_struct {
 	unsigned int save[FP_SOFT_SIZE];		/* undefined information */
 };
 
+#define IWMMXT_SIZE	0x98
+
 struct iwmmxt_struct {
-	unsigned int save[0x98/sizeof(int) + 1];
+	unsigned int save[IWMMXT_SIZE / sizeof(unsigned int)];
 };
 
 union fp_state {
diff --git a/include/asm-arm/thread_info.h b/include/asm-arm/thread_info.h
index 33a33cbb632..cfbccb63c67 100644
--- a/include/asm-arm/thread_info.h
+++ b/include/asm-arm/thread_info.h
@@ -59,7 +59,7 @@ struct thread_info {
 	struct cpu_context_save	cpu_context;	/* cpu context */
 	__u8			used_cp[16];	/* thread used copro */
 	unsigned long		tp_value;
-	union fp_state		fpstate;
+	union fp_state		fpstate __attribute__((aligned(8)));
 	union vfp_state		vfpstate;
 	struct restart_block	restart_block;
 };
-- 
2.41.3