aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/signal.c
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2006-06-24 18:53:01 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-06-24 18:53:01 -0400
commitc0897856553d45aee1780bed455b7c2e888dd64b (patch)
treeacbee1a7cedca5087c3500f991a7de69b68da6b1 /arch/arm/kernel/signal.c
parente11c910b5bcc1dbc38a5af7a24be2812fc956b27 (diff)
parent85fe068123aa11d3477ce88c7d365e233b1f2e10 (diff)
Merge signal handler branch
Diffstat (limited to 'arch/arm/kernel/signal.c')
-rw-r--r--arch/arm/kernel/signal.c207
1 files changed, 82 insertions, 125 deletions
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index f094277485c8..1ce05ec086c6 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,
134 134
135#ifdef CONFIG_IWMMXT 135#ifdef CONFIG_IWMMXT
136 136
137/* iwmmxt_area is 0x98 bytes long, preceeded by 8 bytes of signature */
138#define IWMMXT_STORAGE_SIZE (0x98 + 8)
139#define IWMMXT_MAGIC0 0x12ef842a
140#define IWMMXT_MAGIC1 0x1c07ca71
141
142struct iwmmxt_sigframe {
143 unsigned long magic0;
144 unsigned long magic1;
145 unsigned long storage[0x98/4];
146};
147
148static int preserve_iwmmxt_context(struct iwmmxt_sigframe *frame) 137static int preserve_iwmmxt_context(struct iwmmxt_sigframe *frame)
149{ 138{
150 char kbuf[sizeof(*frame) + 8]; 139 char kbuf[sizeof(*frame) + 8];
@@ -152,8 +141,8 @@ static int preserve_iwmmxt_context(struct iwmmxt_sigframe *frame)
152 141
153 /* the iWMMXt context must be 64 bit aligned */ 142 /* the iWMMXt context must be 64 bit aligned */
154 kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7); 143 kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7);
155 kframe->magic0 = IWMMXT_MAGIC0; 144 kframe->magic = IWMMXT_MAGIC;
156 kframe->magic1 = IWMMXT_MAGIC1; 145 kframe->size = IWMMXT_STORAGE_SIZE;
157 iwmmxt_task_copy(current_thread_info(), &kframe->storage); 146 iwmmxt_task_copy(current_thread_info(), &kframe->storage);
158 return __copy_to_user(frame, kframe, sizeof(*frame)); 147 return __copy_to_user(frame, kframe, sizeof(*frame));
159} 148}
@@ -167,8 +156,8 @@ static int restore_iwmmxt_context(struct iwmmxt_sigframe *frame)
167 kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7); 156 kframe = (struct iwmmxt_sigframe *)((unsigned long)(kbuf + 8) & ~7);
168 if (__copy_from_user(kframe, frame, sizeof(*frame))) 157 if (__copy_from_user(kframe, frame, sizeof(*frame)))
169 return -1; 158 return -1;
170 if (kframe->magic0 != IWMMXT_MAGIC0 || 159 if (kframe->magic != IWMMXT_MAGIC ||
171 kframe->magic1 != IWMMXT_MAGIC1) 160 kframe->size != IWMMXT_STORAGE_SIZE)
172 return -1; 161 return -1;
173 iwmmxt_task_restore(current_thread_info(), &kframe->storage); 162 iwmmxt_task_restore(current_thread_info(), &kframe->storage);
174 return 0; 163 return 0;
@@ -177,70 +166,61 @@ static int restore_iwmmxt_context(struct iwmmxt_sigframe *frame)
177#endif 166#endif
178 167
179/* 168/*
180 * Auxiliary signal frame. This saves stuff like FP state.
181 * The layout of this structure is not part of the user ABI.
182 */
183struct aux_sigframe {
184#ifdef CONFIG_IWMMXT
185 struct iwmmxt_sigframe iwmmxt;
186#endif
187#ifdef CONFIG_VFP
188 union vfp_state vfp;
189#endif
190};
191
192/*
193 * Do a signal return; undo the signal stack. These are aligned to 64-bit. 169 * Do a signal return; undo the signal stack. These are aligned to 64-bit.
194 */ 170 */
195struct sigframe { 171struct sigframe {
196 struct sigcontext sc; 172 struct ucontext uc;
197 unsigned long extramask[_NSIG_WORDS-1];
198 unsigned long retcode[2]; 173 unsigned long retcode[2];
199 struct aux_sigframe aux __attribute__((aligned(8)));
200}; 174};
201 175
202struct rt_sigframe { 176struct rt_sigframe {
203 struct siginfo __user *pinfo;
204 void __user *puc;
205 struct siginfo info; 177 struct siginfo info;
206 struct ucontext uc; 178 struct sigframe sig;
207 unsigned long retcode[2];
208 struct aux_sigframe aux __attribute__((aligned(8)));
209}; 179};
210 180
211static int 181static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
212restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
213 struct aux_sigframe __user *aux)
214{ 182{
215 int err = 0; 183 struct aux_sigframe __user *aux;
184 sigset_t set;
185 int err;
186
187 err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
188 if (err == 0) {
189 sigdelsetmask(&set, ~_BLOCKABLE);
190 spin_lock_irq(&current->sighand->siglock);
191 current->blocked = set;
192 recalc_sigpending();
193 spin_unlock_irq(&current->sighand->siglock);
194 }
216 195
217 __get_user_error(regs->ARM_r0, &sc->arm_r0, err); 196 __get_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err);
218 __get_user_error(regs->ARM_r1, &sc->arm_r1, err); 197 __get_user_error(regs->ARM_r1, &sf->uc.uc_mcontext.arm_r1, err);
219 __get_user_error(regs->ARM_r2, &sc->arm_r2, err); 198 __get_user_error(regs->ARM_r2, &sf->uc.uc_mcontext.arm_r2, err);
220 __get_user_error(regs->ARM_r3, &sc->arm_r3, err); 199 __get_user_error(regs->ARM_r3, &sf->uc.uc_mcontext.arm_r3, err);
221 __get_user_error(regs->ARM_r4, &sc->arm_r4, err); 200 __get_user_error(regs->ARM_r4, &sf->uc.uc_mcontext.arm_r4, err);
222 __get_user_error(regs->ARM_r5, &sc->arm_r5, err); 201 __get_user_error(regs->ARM_r5, &sf->uc.uc_mcontext.arm_r5, err);
223 __get_user_error(regs->ARM_r6, &sc->arm_r6, err); 202 __get_user_error(regs->ARM_r6, &sf->uc.uc_mcontext.arm_r6, err);
224 __get_user_error(regs->ARM_r7, &sc->arm_r7, err); 203 __get_user_error(regs->ARM_r7, &sf->uc.uc_mcontext.arm_r7, err);
225 __get_user_error(regs->ARM_r8, &sc->arm_r8, err); 204 __get_user_error(regs->ARM_r8, &sf->uc.uc_mcontext.arm_r8, err);
226 __get_user_error(regs->ARM_r9, &sc->arm_r9, err); 205 __get_user_error(regs->ARM_r9, &sf->uc.uc_mcontext.arm_r9, err);
227 __get_user_error(regs->ARM_r10, &sc->arm_r10, err); 206 __get_user_error(regs->ARM_r10, &sf->uc.uc_mcontext.arm_r10, err);
228 __get_user_error(regs->ARM_fp, &sc->arm_fp, err); 207 __get_user_error(regs->ARM_fp, &sf->uc.uc_mcontext.arm_fp, err);
229 __get_user_error(regs->ARM_ip, &sc->arm_ip, err); 208 __get_user_error(regs->ARM_ip, &sf->uc.uc_mcontext.arm_ip, err);
230 __get_user_error(regs->ARM_sp, &sc->arm_sp, err); 209 __get_user_error(regs->ARM_sp, &sf->uc.uc_mcontext.arm_sp, err);
231 __get_user_error(regs->ARM_lr, &sc->arm_lr, err); 210 __get_user_error(regs->ARM_lr, &sf->uc.uc_mcontext.arm_lr, err);
232 __get_user_error(regs->ARM_pc, &sc->arm_pc, err); 211 __get_user_error(regs->ARM_pc, &sf->uc.uc_mcontext.arm_pc, err);
233 __get_user_error(regs->ARM_cpsr, &sc->arm_cpsr, err); 212 __get_user_error(regs->ARM_cpsr, &sf->uc.uc_mcontext.arm_cpsr, err);
234 213
235 err |= !valid_user_regs(regs); 214 err |= !valid_user_regs(regs);
236 215
216 aux = (struct aux_sigframe __user *) sf->uc.uc_regspace;
237#ifdef CONFIG_IWMMXT 217#ifdef CONFIG_IWMMXT
238 if (err == 0 && test_thread_flag(TIF_USING_IWMMXT)) 218 if (err == 0 && test_thread_flag(TIF_USING_IWMMXT))
239 err |= restore_iwmmxt_context(&aux->iwmmxt); 219 err |= restore_iwmmxt_context(&aux->iwmmxt);
240#endif 220#endif
241#ifdef CONFIG_VFP 221#ifdef CONFIG_VFP
242// if (err == 0) 222// if (err == 0)
243// err |= vfp_restore_state(&aux->vfp); 223// err |= vfp_restore_state(&sf->aux.vfp);
244#endif 224#endif
245 225
246 return err; 226 return err;
@@ -249,7 +229,6 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
249asmlinkage int sys_sigreturn(struct pt_regs *regs) 229asmlinkage int sys_sigreturn(struct pt_regs *regs)
250{ 230{
251 struct sigframe __user *frame; 231 struct sigframe __user *frame;
252 sigset_t set;
253 232
254 /* Always make any pending restarted system calls return -EINTR */ 233 /* Always make any pending restarted system calls return -EINTR */
255 current_thread_info()->restart_block.fn = do_no_restart_syscall; 234 current_thread_info()->restart_block.fn = do_no_restart_syscall;
@@ -266,19 +245,8 @@ asmlinkage int sys_sigreturn(struct pt_regs *regs)
266 245
267 if (!access_ok(VERIFY_READ, frame, sizeof (*frame))) 246 if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))
268 goto badframe; 247 goto badframe;
269 if (__get_user(set.sig[0], &frame->sc.oldmask)
270 || (_NSIG_WORDS > 1
271 && __copy_from_user(&set.sig[1], &frame->extramask,
272 sizeof(frame->extramask))))
273 goto badframe;
274
275 sigdelsetmask(&set, ~_BLOCKABLE);
276 spin_lock_irq(&current->sighand->siglock);
277 current->blocked = set;
278 recalc_sigpending();
279 spin_unlock_irq(&current->sighand->siglock);
280 248
281 if (restore_sigcontext(regs, &frame->sc, &frame->aux)) 249 if (restore_sigframe(regs, frame))
282 goto badframe; 250 goto badframe;
283 251
284 /* Send SIGTRAP if we're single-stepping */ 252 /* Send SIGTRAP if we're single-stepping */
@@ -297,7 +265,6 @@ badframe:
297asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) 265asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
298{ 266{
299 struct rt_sigframe __user *frame; 267 struct rt_sigframe __user *frame;
300 sigset_t set;
301 268
302 /* Always make any pending restarted system calls return -EINTR */ 269 /* Always make any pending restarted system calls return -EINTR */
303 current_thread_info()->restart_block.fn = do_no_restart_syscall; 270 current_thread_info()->restart_block.fn = do_no_restart_syscall;
@@ -314,19 +281,11 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
314 281
315 if (!access_ok(VERIFY_READ, frame, sizeof (*frame))) 282 if (!access_ok(VERIFY_READ, frame, sizeof (*frame)))
316 goto badframe; 283 goto badframe;
317 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
318 goto badframe;
319 284
320 sigdelsetmask(&set, ~_BLOCKABLE); 285 if (restore_sigframe(regs, &frame->sig))
321 spin_lock_irq(&current->sighand->siglock);
322 current->blocked = set;
323 recalc_sigpending();
324 spin_unlock_irq(&current->sighand->siglock);
325
326 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &frame->aux))
327 goto badframe; 286 goto badframe;
328 287
329 if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->ARM_sp) == -EFAULT) 288 if (do_sigaltstack(&frame->sig.uc.uc_stack, NULL, regs->ARM_sp) == -EFAULT)
330 goto badframe; 289 goto badframe;
331 290
332 /* Send SIGTRAP if we're single-stepping */ 291 /* Send SIGTRAP if we're single-stepping */
@@ -343,42 +302,46 @@ badframe:
343} 302}
344 303
345static int 304static int
346setup_sigcontext(struct sigcontext __user *sc, struct aux_sigframe __user *aux, 305setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs, sigset_t *set)
347 struct pt_regs *regs, unsigned long mask)
348{ 306{
307 struct aux_sigframe __user *aux;
349 int err = 0; 308 int err = 0;
350 309
351 __put_user_error(regs->ARM_r0, &sc->arm_r0, err); 310 __put_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err);
352 __put_user_error(regs->ARM_r1, &sc->arm_r1, err); 311 __put_user_error(regs->ARM_r1, &sf->uc.uc_mcontext.arm_r1, err);
353 __put_user_error(regs->ARM_r2, &sc->arm_r2, err); 312 __put_user_error(regs->ARM_r2, &sf->uc.uc_mcontext.arm_r2, err);
354 __put_user_error(regs->ARM_r3, &sc->arm_r3, err); 313 __put_user_error(regs->ARM_r3, &sf->uc.uc_mcontext.arm_r3, err);
355 __put_user_error(regs->ARM_r4, &sc->arm_r4, err); 314 __put_user_error(regs->ARM_r4, &sf->uc.uc_mcontext.arm_r4, err);
356 __put_user_error(regs->ARM_r5, &sc->arm_r5, err); 315 __put_user_error(regs->ARM_r5, &sf->uc.uc_mcontext.arm_r5, err);
357 __put_user_error(regs->ARM_r6, &sc->arm_r6, err); 316 __put_user_error(regs->ARM_r6, &sf->uc.uc_mcontext.arm_r6, err);
358 __put_user_error(regs->ARM_r7, &sc->arm_r7, err); 317 __put_user_error(regs->ARM_r7, &sf->uc.uc_mcontext.arm_r7, err);
359 __put_user_error(regs->ARM_r8, &sc->arm_r8, err); 318 __put_user_error(regs->ARM_r8, &sf->uc.uc_mcontext.arm_r8, err);
360 __put_user_error(regs->ARM_r9, &sc->arm_r9, err); 319 __put_user_error(regs->ARM_r9, &sf->uc.uc_mcontext.arm_r9, err);
361 __put_user_error(regs->ARM_r10, &sc->arm_r10, err); 320 __put_user_error(regs->ARM_r10, &sf->uc.uc_mcontext.arm_r10, err);
362 __put_user_error(regs->ARM_fp, &sc->arm_fp, err); 321 __put_user_error(regs->ARM_fp, &sf->uc.uc_mcontext.arm_fp, err);
363 __put_user_error(regs->ARM_ip, &sc->arm_ip, err); 322 __put_user_error(regs->ARM_ip, &sf->uc.uc_mcontext.arm_ip, err);
364 __put_user_error(regs->ARM_sp, &sc->arm_sp, err); 323 __put_user_error(regs->ARM_sp, &sf->uc.uc_mcontext.arm_sp, err);
365 __put_user_error(regs->ARM_lr, &sc->arm_lr, err); 324 __put_user_error(regs->ARM_lr, &sf->uc.uc_mcontext.arm_lr, err);
366 __put_user_error(regs->ARM_pc, &sc->arm_pc, err); 325 __put_user_error(regs->ARM_pc, &sf->uc.uc_mcontext.arm_pc, err);
367 __put_user_error(regs->ARM_cpsr, &sc->arm_cpsr, err); 326 __put_user_error(regs->ARM_cpsr, &sf->uc.uc_mcontext.arm_cpsr, err);
368 327
369 __put_user_error(current->thread.trap_no, &sc->trap_no, err); 328 __put_user_error(current->thread.trap_no, &sf->uc.uc_mcontext.trap_no, err);
370 __put_user_error(current->thread.error_code, &sc->error_code, err); 329 __put_user_error(current->thread.error_code, &sf->uc.uc_mcontext.error_code, err);
371 __put_user_error(current->thread.address, &sc->fault_address, err); 330 __put_user_error(current->thread.address, &sf->uc.uc_mcontext.fault_address, err);
372 __put_user_error(mask, &sc->oldmask, err); 331 __put_user_error(set->sig[0], &sf->uc.uc_mcontext.oldmask, err);
373 332
333 err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set));
334
335 aux = (struct aux_sigframe __user *) sf->uc.uc_regspace;
374#ifdef CONFIG_IWMMXT 336#ifdef CONFIG_IWMMXT
375 if (err == 0 && test_thread_flag(TIF_USING_IWMMXT)) 337 if (err == 0 && test_thread_flag(TIF_USING_IWMMXT))
376 err |= preserve_iwmmxt_context(&aux->iwmmxt); 338 err |= preserve_iwmmxt_context(&aux->iwmmxt);
377#endif 339#endif
378#ifdef CONFIG_VFP 340#ifdef CONFIG_VFP
379// if (err == 0) 341// if (err == 0)
380// err |= vfp_save_state(&aux->vfp); 342// err |= vfp_save_state(&sf->aux.vfp);
381#endif 343#endif
344 __put_user_error(0, &aux->end_magic, err);
382 345
383 return err; 346 return err;
384} 347}
@@ -487,13 +450,12 @@ setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *reg
487 if (!frame) 450 if (!frame)
488 return 1; 451 return 1;
489 452
490 err |= setup_sigcontext(&frame->sc, &frame->aux, regs, set->sig[0]); 453 /*
491 454 * Set uc.uc_flags to a value which sc.trap_no would never have.
492 if (_NSIG_WORDS > 1) { 455 */
493 err |= __copy_to_user(frame->extramask, &set->sig[1], 456 __put_user_error(0x5ac3c35a, &frame->uc.uc_flags, err);
494 sizeof(frame->extramask));
495 }
496 457
458 err |= setup_sigframe(frame, regs, set);
497 if (err == 0) 459 if (err == 0)
498 err = setup_return(regs, ka, frame->retcode, frame, usig); 460 err = setup_return(regs, ka, frame->retcode, frame, usig);
499 461
@@ -511,25 +473,20 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
511 if (!frame) 473 if (!frame)
512 return 1; 474 return 1;
513 475
514 __put_user_error(&frame->info, &frame->pinfo, err);
515 __put_user_error(&frame->uc, &frame->puc, err);
516 err |= copy_siginfo_to_user(&frame->info, info); 476 err |= copy_siginfo_to_user(&frame->info, info);
517 477
518 __put_user_error(0, &frame->uc.uc_flags, err); 478 __put_user_error(0, &frame->sig.uc.uc_flags, err);
519 __put_user_error(NULL, &frame->uc.uc_link, err); 479 __put_user_error(NULL, &frame->sig.uc.uc_link, err);
520 480
521 memset(&stack, 0, sizeof(stack)); 481 memset(&stack, 0, sizeof(stack));
522 stack.ss_sp = (void __user *)current->sas_ss_sp; 482 stack.ss_sp = (void __user *)current->sas_ss_sp;
523 stack.ss_flags = sas_ss_flags(regs->ARM_sp); 483 stack.ss_flags = sas_ss_flags(regs->ARM_sp);
524 stack.ss_size = current->sas_ss_size; 484 stack.ss_size = current->sas_ss_size;
525 err |= __copy_to_user(&frame->uc.uc_stack, &stack, sizeof(stack)); 485 err |= __copy_to_user(&frame->sig.uc.uc_stack, &stack, sizeof(stack));
526
527 err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->aux,
528 regs, set->sig[0]);
529 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
530 486
487 err |= setup_sigframe(&frame->sig, regs, set);
531 if (err == 0) 488 if (err == 0)
532 err = setup_return(regs, ka, frame->retcode, frame, usig); 489 err = setup_return(regs, ka, frame->sig.retcode, frame, usig);
533 490
534 if (err == 0) { 491 if (err == 0) {
535 /* 492 /*
@@ -538,7 +495,7 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
538 * -- Peter Maydell <pmaydell@chiark.greenend.org.uk> 2000-12-06 495 * -- Peter Maydell <pmaydell@chiark.greenend.org.uk> 2000-12-06
539 */ 496 */
540 regs->ARM_r1 = (unsigned long)&frame->info; 497 regs->ARM_r1 = (unsigned long)&frame->info;
541 regs->ARM_r2 = (unsigned long)&frame->uc; 498 regs->ARM_r2 = (unsigned long)&frame->sig.uc;
542 } 499 }
543 500
544 return err; 501 return err;