diff options
| author | Russell King <rmk@dyn-67.arm.linux.org.uk> | 2006-06-24 18:53:01 -0400 |
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2006-06-24 18:53:01 -0400 |
| commit | c0897856553d45aee1780bed455b7c2e888dd64b (patch) | |
| tree | acbee1a7cedca5087c3500f991a7de69b68da6b1 | |
| parent | e11c910b5bcc1dbc38a5af7a24be2812fc956b27 (diff) | |
| parent | 85fe068123aa11d3477ce88c7d365e233b1f2e10 (diff) | |
Merge signal handler branch
| -rw-r--r-- | arch/arm/kernel/signal.c | 207 | ||||
| -rw-r--r-- | include/asm-arm/ucontext.h | 79 |
2 files changed, 160 insertions, 126 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 | |||
| 142 | struct iwmmxt_sigframe { | ||
| 143 | unsigned long magic0; | ||
| 144 | unsigned long magic1; | ||
| 145 | unsigned long storage[0x98/4]; | ||
| 146 | }; | ||
| 147 | |||
| 148 | static int preserve_iwmmxt_context(struct iwmmxt_sigframe *frame) | 137 | static 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 | */ | ||
| 183 | struct 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 | */ |
| 195 | struct sigframe { | 171 | struct 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 | ||
| 202 | struct rt_sigframe { | 176 | struct 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 | ||
| 211 | static int | 181 | static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf) |
| 212 | restore_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(¤t->sighand->siglock); | ||
| 191 | current->blocked = set; | ||
| 192 | recalc_sigpending(); | ||
| 193 | spin_unlock_irq(¤t->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, | |||
| 249 | asmlinkage int sys_sigreturn(struct pt_regs *regs) | 229 | asmlinkage 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(¤t->sighand->siglock); | ||
| 277 | current->blocked = set; | ||
| 278 | recalc_sigpending(); | ||
| 279 | spin_unlock_irq(¤t->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: | |||
| 297 | asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) | 265 | asmlinkage 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(¤t->sighand->siglock); | ||
| 322 | current->blocked = set; | ||
| 323 | recalc_sigpending(); | ||
| 324 | spin_unlock_irq(¤t->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 | ||
| 345 | static int | 304 | static int |
| 346 | setup_sigcontext(struct sigcontext __user *sc, struct aux_sigframe __user *aux, | 305 | setup_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; |
diff --git a/include/asm-arm/ucontext.h b/include/asm-arm/ucontext.h index f853130137cc..9e6f7ca9f5ae 100644 --- a/include/asm-arm/ucontext.h +++ b/include/asm-arm/ucontext.h | |||
| @@ -1,12 +1,89 @@ | |||
| 1 | #ifndef _ASMARM_UCONTEXT_H | 1 | #ifndef _ASMARM_UCONTEXT_H |
| 2 | #define _ASMARM_UCONTEXT_H | 2 | #define _ASMARM_UCONTEXT_H |
| 3 | 3 | ||
| 4 | #include <asm/fpstate.h> | ||
| 5 | |||
| 6 | /* | ||
| 7 | * struct sigcontext only has room for the basic registers, but struct | ||
| 8 | * ucontext now has room for all registers which need to be saved and | ||
| 9 | * restored. Coprocessor registers are stored in uc_regspace. Each | ||
| 10 | * coprocessor's saved state should start with a documented 32-bit magic | ||
| 11 | * number, followed by a 32-bit word giving the coproccesor's saved size. | ||
| 12 | * uc_regspace may be expanded if necessary, although this takes some | ||
| 13 | * coordination with glibc. | ||
| 14 | */ | ||
| 15 | |||
| 4 | struct ucontext { | 16 | struct ucontext { |
| 5 | unsigned long uc_flags; | 17 | unsigned long uc_flags; |
| 6 | struct ucontext *uc_link; | 18 | struct ucontext *uc_link; |
| 7 | stack_t uc_stack; | 19 | stack_t uc_stack; |
| 8 | struct sigcontext uc_mcontext; | 20 | struct sigcontext uc_mcontext; |
| 9 | sigset_t uc_sigmask; /* mask last for extensibility */ | 21 | sigset_t uc_sigmask; |
| 22 | /* Allow for uc_sigmask growth. Glibc uses a 1024-bit sigset_t. */ | ||
| 23 | int __unused[32 - (sizeof (sigset_t) / sizeof (int))]; | ||
| 24 | /* Last for extensibility. Eight byte aligned because some | ||
| 25 | coprocessors require eight byte alignment. */ | ||
| 26 | unsigned long uc_regspace[128] __attribute__((__aligned__(8))); | ||
| 10 | }; | 27 | }; |
| 11 | 28 | ||
| 29 | #ifdef __KERNEL__ | ||
| 30 | |||
| 31 | /* | ||
| 32 | * Coprocessor save state. The magic values and specific | ||
| 33 | * coprocessor's layouts are part of the userspace ABI. Each one of | ||
| 34 | * these should be a multiple of eight bytes and aligned to eight | ||
| 35 | * bytes, to prevent unpredictable padding in the signal frame. | ||
| 36 | */ | ||
| 37 | |||
| 38 | #ifdef CONFIG_IWMMXT | ||
| 39 | /* iwmmxt_area is 0x98 bytes long, preceeded by 8 bytes of signature */ | ||
| 40 | #define IWMMXT_MAGIC 0x12ef842a | ||
| 41 | #define IWMMXT_STORAGE_SIZE (IWMMXT_SIZE + 8) | ||
| 42 | |||
| 43 | struct iwmmxt_sigframe { | ||
| 44 | unsigned long magic; | ||
| 45 | unsigned long size; | ||
| 46 | struct iwmmxt_struct storage; | ||
| 47 | } __attribute__((__aligned__(8))); | ||
| 48 | #endif /* CONFIG_IWMMXT */ | ||
| 49 | |||
| 50 | #ifdef CONFIG_VFP | ||
| 51 | #if __LINUX_ARM_ARCH__ < 6 | ||
| 52 | /* For ARM pre-v6, we use fstmiax and fldmiax. This adds one extra | ||
| 53 | * word after the registers, and a word of padding at the end for | ||
| 54 | * alignment. */ | ||
| 55 | #define VFP_MAGIC 0x56465001 | ||
| 56 | #define VFP_STORAGE_SIZE 152 | ||
| 57 | #else | ||
| 58 | #define VFP_MAGIC 0x56465002 | ||
| 59 | #define VFP_STORAGE_SIZE 144 | ||
| 60 | #endif | ||
| 61 | |||
| 62 | struct vfp_sigframe | ||
| 63 | { | ||
| 64 | unsigned long magic; | ||
| 65 | unsigned long size; | ||
| 66 | union vfp_state storage; | ||
| 67 | }; | ||
| 68 | #endif /* CONFIG_VFP */ | ||
| 69 | |||
| 70 | /* | ||
| 71 | * Auxiliary signal frame. This saves stuff like FP state. | ||
| 72 | * The layout of this structure is not part of the user ABI, | ||
| 73 | * because the config options aren't. uc_regspace is really | ||
| 74 | * one of these. | ||
| 75 | */ | ||
| 76 | struct aux_sigframe { | ||
| 77 | #ifdef CONFIG_IWMMXT | ||
| 78 | struct iwmmxt_sigframe iwmmxt; | ||
| 79 | #endif | ||
| 80 | #if 0 && defined CONFIG_VFP /* Not yet saved. */ | ||
| 81 | struct vfp_sigframe vfp; | ||
| 82 | #endif | ||
| 83 | /* Something that isn't a valid magic number for any coprocessor. */ | ||
| 84 | unsigned long end_magic; | ||
| 85 | } __attribute__((__aligned__(8))); | ||
| 86 | |||
| 87 | #endif | ||
| 88 | |||
| 12 | #endif /* !_ASMARM_UCONTEXT_H */ | 89 | #endif /* !_ASMARM_UCONTEXT_H */ |
