diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index c0ba8afee42fd..e5802bfda31df 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -134,17 +134,6 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
 
 #ifdef CONFIG_IWMMXT
 
-/* iwmmxt_area is 0x98 bytes long, preceeded by 8 bytes of signature */
-#define IWMMXT_STORAGE_SIZE	(0x98 + 8)
-#define IWMMXT_MAGIC0		0x12ef842a
-#define IWMMXT_MAGIC1		0x1c07ca71
-
-struct iwmmxt_sigframe {
-	unsigned long	magic0;
-	unsigned long	magic1;
-	unsigned long	storage[0x98/4];
-};
-
 static int preserve_iwmmxt_context(struct iwmmxt_sigframe *frame)
 {
 	char kbuf[sizeof(*frame) + 8];
@@ -152,8 +141,8 @@ static int preserve_iwmmxt_context(struct iwmmxt_sigframe *frame)
 
 	/* the iWMMXt context must be 64 bit aligned */
 	kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7);
-	kframe->magic0 = IWMMXT_MAGIC0;
-	kframe->magic1 = IWMMXT_MAGIC1;
+	kframe->magic = IWMMXT_MAGIC;
+	kframe->size = IWMMXT_STORAGE_SIZE;
 	iwmmxt_task_copy(current_thread_info(), &kframe->storage);
 	return __copy_to_user(frame, kframe, sizeof(*frame));
 }
@@ -167,8 +156,8 @@ static int restore_iwmmxt_context(struct iwmmxt_sigframe *frame)
 	kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7);
 	if (__copy_from_user(kframe, frame, sizeof(*frame)))
 		return -1;
-	if (kframe->magic0 != IWMMXT_MAGIC0 ||
-	    kframe->magic1 != IWMMXT_MAGIC1)
+	if (kframe->magic != IWMMXT_MAGIC ||
+	    kframe->size != IWMMXT_STORAGE_SIZE)
 		return -1;
 	iwmmxt_task_restore(current_thread_info(), &kframe->storage);
 	return 0;
@@ -176,26 +165,12 @@ static int restore_iwmmxt_context(struct iwmmxt_sigframe *frame)
 
 #endif
 
-/*
- * Auxiliary signal frame.  This saves stuff like FP state.
- * The layout of this structure is not part of the user ABI.
- */
-struct aux_sigframe {
-#ifdef CONFIG_IWMMXT
-	struct iwmmxt_sigframe	iwmmxt;
-#endif
-#ifdef CONFIG_VFP
-	union vfp_state		vfp;
-#endif
-};
-
 /*
  * Do a signal return; undo the signal stack.  These are aligned to 64-bit.
  */
 struct sigframe {
 	struct ucontext uc;
 	unsigned long retcode[2];
-	struct aux_sigframe aux __attribute__((aligned(8)));
 };
 
 struct rt_sigframe {
@@ -205,6 +180,7 @@ struct rt_sigframe {
 
 static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
 {
+	struct aux_sigframe __user *aux;
 	sigset_t set;
 	int err;
 
@@ -237,9 +213,10 @@ static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
 
 	err |= !valid_user_regs(regs);
 
+	aux = (struct aux_sigframe __user *) sf->uc.uc_regspace;
 #ifdef CONFIG_IWMMXT
 	if (err == 0 && test_thread_flag(TIF_USING_IWMMXT))
-		err |= restore_iwmmxt_context(&sf->aux.iwmmxt);
+		err |= restore_iwmmxt_context(&aux->iwmmxt);
 #endif
 #ifdef CONFIG_VFP
 //	if (err == 0)
@@ -327,6 +304,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
 static int
 setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs, sigset_t *set)
 {
+	struct aux_sigframe __user *aux;
 	int err = 0;
 
 	__put_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err);
@@ -354,14 +332,16 @@ setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs, sigset_t *set)
 
 	err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set));
 
+	aux = (struct aux_sigframe __user *) sf->uc.uc_regspace;
 #ifdef CONFIG_IWMMXT
 	if (err == 0 && test_thread_flag(TIF_USING_IWMMXT))
-		err |= preserve_iwmmxt_context(&sf->aux.iwmmxt);
+		err |= preserve_iwmmxt_context(&aux->iwmmxt);
 #endif
 #ifdef CONFIG_VFP
 //	if (err == 0)
 //		err |= vfp_save_state(&sf->aux.vfp);
 #endif
+	__put_user_error(0, &aux->end_magic, err);
 
 	return err;
 }
diff --git a/include/asm-arm/ucontext.h b/include/asm-arm/ucontext.h
index f853130137cce..9e6f7ca9f5ae3 100644
--- a/include/asm-arm/ucontext.h
+++ b/include/asm-arm/ucontext.h
@@ -1,12 +1,89 @@
 #ifndef _ASMARM_UCONTEXT_H
 #define _ASMARM_UCONTEXT_H
 
+#include <asm/fpstate.h>
+
+/*
+ * struct sigcontext only has room for the basic registers, but struct
+ * ucontext now has room for all registers which need to be saved and
+ * restored.  Coprocessor registers are stored in uc_regspace.  Each
+ * coprocessor's saved state should start with a documented 32-bit magic
+ * number, followed by a 32-bit word giving the coproccesor's saved size.
+ * uc_regspace may be expanded if necessary, although this takes some
+ * coordination with glibc.
+ */
+
 struct ucontext {
 	unsigned long	  uc_flags;
 	struct ucontext  *uc_link;
 	stack_t		  uc_stack;
 	struct sigcontext uc_mcontext;
-	sigset_t	  uc_sigmask;	/* mask last for extensibility */
+	sigset_t	  uc_sigmask;
+	/* Allow for uc_sigmask growth.  Glibc uses a 1024-bit sigset_t.  */
+	int		  __unused[32 - (sizeof (sigset_t) / sizeof (int))];
+	/* Last for extensibility.  Eight byte aligned because some
+	   coprocessors require eight byte alignment.  */
+ 	unsigned long	  uc_regspace[128] __attribute__((__aligned__(8)));
 };
 
+#ifdef __KERNEL__
+
+/*
+ * Coprocessor save state.  The magic values and specific
+ * coprocessor's layouts are part of the userspace ABI.  Each one of
+ * these should be a multiple of eight bytes and aligned to eight
+ * bytes, to prevent unpredictable padding in the signal frame.
+ */
+
+#ifdef CONFIG_IWMMXT
+/* iwmmxt_area is 0x98 bytes long, preceeded by 8 bytes of signature */
+#define IWMMXT_MAGIC		0x12ef842a
+#define IWMMXT_STORAGE_SIZE	(IWMMXT_SIZE + 8)
+
+struct iwmmxt_sigframe {
+	unsigned long	magic;
+	unsigned long	size;
+	struct iwmmxt_struct storage;
+} __attribute__((__aligned__(8)));
+#endif /* CONFIG_IWMMXT */
+
+#ifdef CONFIG_VFP
+#if __LINUX_ARM_ARCH__ < 6
+/* For ARM pre-v6, we use fstmiax and fldmiax.  This adds one extra
+ * word after the registers, and a word of padding at the end for
+ * alignment.  */
+#define VFP_MAGIC		0x56465001
+#define VFP_STORAGE_SIZE	152
+#else
+#define VFP_MAGIC		0x56465002
+#define VFP_STORAGE_SIZE	144
+#endif
+
+struct vfp_sigframe
+{
+	unsigned long		magic;
+	unsigned long		size;
+	union vfp_state		storage;
+};
+#endif /* CONFIG_VFP */
+
+/*
+ * Auxiliary signal frame.  This saves stuff like FP state.
+ * The layout of this structure is not part of the user ABI,
+ * because the config options aren't.  uc_regspace is really
+ * one of these.
+ */
+struct aux_sigframe {
+#ifdef CONFIG_IWMMXT
+	struct iwmmxt_sigframe	iwmmxt;
+#endif
+#if 0 && defined CONFIG_VFP /* Not yet saved.  */
+	struct vfp_sigframe	vfp;
+#endif
+	/* Something that isn't a valid magic number for any coprocessor.  */
+	unsigned long		end_magic;
+} __attribute__((__aligned__(8)));
+
+#endif
+
 #endif /* !_ASMARM_UCONTEXT_H */