aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLennert Buytenhek <buytenh@wantstofly.org>2006-06-27 17:56:18 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-06-28 12:54:59 -0400
commit3bec6ded282b331552587267d67a06ed7fd95ddd (patch)
tree5333fa3e3322528e3d8e5074d41ffc7f538f6768 /arch
parent562ca1e32a9c2514551559691db809606502a15a (diff)
[ARM] 3664/1: crunch: add signal frame save/restore
Patch from Lennert Buytenhek This patch makes the kernel save Crunch state in userland signal frames, so that any userland signal handler can safely use the Crunch coprocessor without corrupting the Crunch state of the code it preempted. Signed-off-by: Lennert Buytenhek <buytenh@wantstofly.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/kernel/signal.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 1ce05ec086c6..83a8d3c95eb3 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -132,6 +132,37 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
132 return ret; 132 return ret;
133} 133}
134 134
135#ifdef CONFIG_CRUNCH
136static int preserve_crunch_context(struct crunch_sigframe *frame)
137{
138 char kbuf[sizeof(*frame) + 8];
139 struct crunch_sigframe *kframe;
140
141 /* the crunch context must be 64 bit aligned */
142 kframe = (struct crunch_sigframe *)((unsigned long)(kbuf + 8) & ~7);
143 kframe->magic = CRUNCH_MAGIC;
144 kframe->size = CRUNCH_STORAGE_SIZE;
145 crunch_task_copy(current_thread_info(), &kframe->storage);
146 return __copy_to_user(frame, kframe, sizeof(*frame));
147}
148
149static int restore_crunch_context(struct crunch_sigframe *frame)
150{
151 char kbuf[sizeof(*frame) + 8];
152 struct crunch_sigframe *kframe;
153
154 /* the crunch context must be 64 bit aligned */
155 kframe = (struct crunch_sigframe *)((unsigned long)(kbuf + 8) & ~7);
156 if (__copy_from_user(kframe, frame, sizeof(*frame)))
157 return -1;
158 if (kframe->magic != CRUNCH_MAGIC ||
159 kframe->size != CRUNCH_STORAGE_SIZE)
160 return -1;
161 crunch_task_restore(current_thread_info(), &kframe->storage);
162 return 0;
163}
164#endif
165
135#ifdef CONFIG_IWMMXT 166#ifdef CONFIG_IWMMXT
136 167
137static int preserve_iwmmxt_context(struct iwmmxt_sigframe *frame) 168static int preserve_iwmmxt_context(struct iwmmxt_sigframe *frame)
@@ -214,6 +245,10 @@ static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
214 err |= !valid_user_regs(regs); 245 err |= !valid_user_regs(regs);
215 246
216 aux = (struct aux_sigframe __user *) sf->uc.uc_regspace; 247 aux = (struct aux_sigframe __user *) sf->uc.uc_regspace;
248#ifdef CONFIG_CRUNCH
249 if (err == 0)
250 err |= restore_crunch_context(&aux->crunch);
251#endif
217#ifdef CONFIG_IWMMXT 252#ifdef CONFIG_IWMMXT
218 if (err == 0 && test_thread_flag(TIF_USING_IWMMXT)) 253 if (err == 0 && test_thread_flag(TIF_USING_IWMMXT))
219 err |= restore_iwmmxt_context(&aux->iwmmxt); 254 err |= restore_iwmmxt_context(&aux->iwmmxt);
@@ -333,6 +368,10 @@ setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs, sigset_t *set)
333 err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set)); 368 err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set));
334 369
335 aux = (struct aux_sigframe __user *) sf->uc.uc_regspace; 370 aux = (struct aux_sigframe __user *) sf->uc.uc_regspace;
371#ifdef CONFIG_CRUNCH
372 if (err == 0)
373 err |= preserve_crunch_context(&aux->crunch);
374#endif
336#ifdef CONFIG_IWMMXT 375#ifdef CONFIG_IWMMXT
337 if (err == 0 && test_thread_flag(TIF_USING_IWMMXT)) 376 if (err == 0 && test_thread_flag(TIF_USING_IWMMXT))
338 err |= preserve_iwmmxt_context(&aux->iwmmxt); 377 err |= preserve_iwmmxt_context(&aux->iwmmxt);