summaryrefslogtreecommitdiffstats
path: root/extras/recipes-kernel/linux/linux-omap-psp-2.6.32/0032-ARM-VFP-preserve-the-HW-context-when-calling-signal-.patch
diff options
context:
space:
mode:
Diffstat (limited to 'extras/recipes-kernel/linux/linux-omap-psp-2.6.32/0032-ARM-VFP-preserve-the-HW-context-when-calling-signal-.patch')
-rw-r--r--extras/recipes-kernel/linux/linux-omap-psp-2.6.32/0032-ARM-VFP-preserve-the-HW-context-when-calling-signal-.patch211
1 files changed, 211 insertions, 0 deletions
diff --git a/extras/recipes-kernel/linux/linux-omap-psp-2.6.32/0032-ARM-VFP-preserve-the-HW-context-when-calling-signal-.patch b/extras/recipes-kernel/linux/linux-omap-psp-2.6.32/0032-ARM-VFP-preserve-the-HW-context-when-calling-signal-.patch
new file mode 100644
index 00000000..f2571306
--- /dev/null
+++ b/extras/recipes-kernel/linux/linux-omap-psp-2.6.32/0032-ARM-VFP-preserve-the-HW-context-when-calling-signal-.patch
@@ -0,0 +1,211 @@
1From 1be18045f852e78bf78d2042a5210c53d830f81b Mon Sep 17 00:00:00 2001
2From: Imre Deak <imre.deak@nokia.com>
3Date: Thu, 4 Feb 2010 21:38:30 +0200
4Subject: [PATCH 32/45] ARM: VFP: preserve the HW context when calling signal handlers
5
6ARM: VFP: preserve the HW context when calling signal handlers
7
8Signal handlers can use floating point, so prevent them to corrupt
9the main thread's VFP context. So far there were two signal stack
10frame formats defined based on the VFP implementation, but the user
11struct used for ptrace covers all posibilities, so use it for the
12signal stack too. This patch extends the user struct and leaves
13its magic number the same, in the hope that user space code does
14not depend on its size and can parse the original regs w/o
15problems.
16
17Support to save / restore the exception registers was added by
18Will Deacon.
19
20Signed-off-by: Imre Deak <imre.deak@nokia.com>
21Signed-off-by: Will Deacon <will.deacon@arm.com>
22Signed-off-by: Bryan Wu <bryan.wu@canonical.com>
23---
24 arch/arm/include/asm/ucontext.h | 19 +++-----
25 arch/arm/include/asm/user.h | 3 +
26 arch/arm/kernel/signal.c | 91 +++++++++++++++++++++++++++++++++++++--
27 3 files changed, 97 insertions(+), 16 deletions(-)
28
29diff --git a/arch/arm/include/asm/ucontext.h b/arch/arm/include/asm/ucontext.h
30index bf65e9f..1c3236b 100644
31--- a/arch/arm/include/asm/ucontext.h
32+++ b/arch/arm/include/asm/ucontext.h
33@@ -59,23 +59,18 @@ struct iwmmxt_sigframe {
34 #endif /* CONFIG_IWMMXT */
35
36 #ifdef CONFIG_VFP
37-#if __LINUX_ARM_ARCH__ < 6
38-/* For ARM pre-v6, we use fstmiax and fldmiax. This adds one extra
39- * word after the registers, and a word of padding at the end for
40- * alignment. */
41 #define VFP_MAGIC 0x56465001
42-#define VFP_STORAGE_SIZE 152
43-#else
44-#define VFP_MAGIC 0x56465002
45-#define VFP_STORAGE_SIZE 144
46-#endif
47
48 struct vfp_sigframe
49 {
50 unsigned long magic;
51 unsigned long size;
52- union vfp_state storage;
53-};
54+ struct user_vfp ufp;
55+} __attribute__((__aligned__(8)));
56+
57+/* 8 byte for magic and size, 272 byte for ufp */
58+#define VFP_STORAGE_SIZE sizeof(struct vfp_sigframe)
59+
60 #endif /* CONFIG_VFP */
61
62 /*
63@@ -91,7 +86,7 @@ struct aux_sigframe {
64 #ifdef CONFIG_IWMMXT
65 struct iwmmxt_sigframe iwmmxt;
66 #endif
67-#if 0 && defined CONFIG_VFP /* Not yet saved. */
68+#ifdef CONFIG_VFP
69 struct vfp_sigframe vfp;
70 #endif
71 /* Something that isn't a valid magic number for any coprocessor. */
72diff --git a/arch/arm/include/asm/user.h b/arch/arm/include/asm/user.h
73index df95e05..ea7e44d 100644
74--- a/arch/arm/include/asm/user.h
75+++ b/arch/arm/include/asm/user.h
76@@ -88,6 +88,9 @@ struct user{
77 struct user_vfp {
78 unsigned long long fpregs[32];
79 unsigned long fpscr;
80+ unsigned long fpexc;
81+ unsigned long fpinst;
82+ unsigned long fpinst2;
83 };
84
85 #endif /* _ARM_USER_H */
86diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
87index e7714f3..6a36851 100644
88--- a/arch/arm/kernel/signal.c
89+++ b/arch/arm/kernel/signal.c
90@@ -18,6 +18,7 @@
91 #include <asm/cacheflush.h>
92 #include <asm/ucontext.h>
93 #include <asm/unistd.h>
94+#include <asm/vfp.h>
95
96 #include "ptrace.h"
97 #include "signal.h"
98@@ -175,6 +176,88 @@ static int restore_iwmmxt_context(struct iwmmxt_sigframe *frame)
99
100 #endif
101
102+#ifdef CONFIG_VFP
103+
104+static int preserve_vfp_context(struct vfp_sigframe __user *frame)
105+{
106+ struct thread_info *thread = current_thread_info();
107+ struct vfp_hard_struct *h = &thread->vfpstate.hard;
108+ const unsigned long magic = VFP_MAGIC;
109+ const unsigned long size = VFP_STORAGE_SIZE;
110+ int err = 0;
111+
112+ vfp_sync_state(thread);
113+ __put_user_error(magic, &frame->magic, err);
114+ __put_user_error(size, &frame->size, err);
115+
116+ /*
117+ * Copy the floating point registers. There can be unused
118+ * registers see asm/hwcap.h for details.
119+ */
120+ err |= __copy_to_user(&frame->ufp.fpregs, &h->fpregs,
121+ sizeof(h->fpregs));
122+ /*
123+ * Copy the status and control register.
124+ */
125+ __put_user_error(h->fpscr, &frame->ufp.fpscr, err);
126+
127+ /*
128+ * Copy the exception registers.
129+ */
130+ __put_user_error(h->fpexc, &frame->ufp.fpexc, err);
131+ __put_user_error(h->fpinst, &frame->ufp.fpinst, err);
132+ __put_user_error(h->fpinst2, &frame->ufp.fpinst2, err);
133+
134+ return err ? -EFAULT : 0;
135+}
136+
137+static int restore_vfp_context(struct vfp_sigframe __user *frame)
138+{
139+ struct thread_info *thread = current_thread_info();
140+ struct vfp_hard_struct *h = &thread->vfpstate.hard;
141+ unsigned long magic;
142+ unsigned long size;
143+ unsigned long fpexc;
144+ int err = 0;
145+
146+ vfp_sync_state(thread);
147+ __get_user_error(magic, &frame->magic, err);
148+ __get_user_error(size, &frame->size, err);
149+
150+ if (err)
151+ return -EFAULT;
152+ if (magic != VFP_MAGIC || size != VFP_STORAGE_SIZE)
153+ return -EINVAL;
154+
155+ /*
156+ * Copy the floating point registers. There can be unused
157+ * registers see asm/hwcap.h for details.
158+ */
159+ err |= __copy_from_user(&h->fpregs, &frame->ufp.fpregs,
160+ sizeof(h->fpregs));
161+ /*
162+ * Copy the status and control register.
163+ */
164+ __get_user_error(h->fpscr, &frame->ufp.fpscr, err);
165+
166+ /*
167+ * Sanitise and restore the exception registers.
168+ */
169+ __get_user_error(fpexc, &frame->ufp.fpexc, err);
170+ /* Ensure the VFP is enabled. */
171+ fpexc |= FPEXC_EN;
172+ /* Ensure FPINST2 is invalid and the exception flag is cleared. */
173+ fpexc &= ~(FPEXC_EX | FPEXC_FP2V);
174+ h->fpexc = fpexc;
175+
176+ __get_user_error(h->fpinst, &frame->ufp.fpinst, err);
177+ __get_user_error(h->fpinst2, &frame->ufp.fpinst2, err);
178+
179+ return err ? -EFAULT : 0;
180+}
181+
182+#endif
183+
184 /*
185 * Do a signal return; undo the signal stack. These are aligned to 64-bit.
186 */
187@@ -233,8 +316,8 @@ static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
188 err |= restore_iwmmxt_context(&aux->iwmmxt);
189 #endif
190 #ifdef CONFIG_VFP
191-// if (err == 0)
192-// err |= vfp_restore_state(&sf->aux.vfp);
193+ if (err == 0)
194+ err |= restore_vfp_context(&aux->vfp);
195 #endif
196
197 return err;
198@@ -348,8 +431,8 @@ setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs, sigset_t *set)
199 err |= preserve_iwmmxt_context(&aux->iwmmxt);
200 #endif
201 #ifdef CONFIG_VFP
202-// if (err == 0)
203-// err |= vfp_save_state(&sf->aux.vfp);
204+ if (err == 0)
205+ err |= preserve_vfp_context(&aux->vfp);
206 #endif
207 __put_user_error(0, &aux->end_magic, err);
208
209--
2101.6.6.1
211