aboutsummaryrefslogtreecommitdiffstats
path: root/arch/microblaze/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/microblaze/kernel/signal.c')
-rw-r--r--arch/microblaze/kernel/signal.c109
1 files changed, 21 insertions, 88 deletions
diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c
index 40d36931e363..4c0e6521b114 100644
--- a/arch/microblaze/kernel/signal.c
+++ b/arch/microblaze/kernel/signal.c
@@ -152,8 +152,8 @@ struct rt_sigframe {
152 unsigned long tramp[2]; /* signal trampoline */ 152 unsigned long tramp[2]; /* signal trampoline */
153}; 153};
154 154
155static int 155static int restore_sigcontext(struct pt_regs *regs,
156restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *rval_p) 156 struct sigcontext __user *sc, int *rval_p)
157{ 157{
158 unsigned int err = 0; 158 unsigned int err = 0;
159 159
@@ -211,11 +211,10 @@ badframe:
211 211
212asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) 212asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
213{ 213{
214 struct rt_sigframe *frame = 214 struct rt_sigframe __user *frame =
215 (struct rt_sigframe *)(regs->r1 + STATE_SAVE_ARG_SPACE); 215 (struct rt_sigframe __user *)(regs->r1 + STATE_SAVE_ARG_SPACE);
216 216
217 sigset_t set; 217 sigset_t set;
218 stack_t st;
219 int rval; 218 int rval;
220 219
221 if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) 220 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
@@ -233,11 +232,10 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
233 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval)) 232 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval))
234 goto badframe; 233 goto badframe;
235 234
236 if (__copy_from_user((void *)&st, &frame->uc.uc_stack, sizeof(st)))
237 goto badframe;
238 /* It is more difficult to avoid calling this function than to 235 /* It is more difficult to avoid calling this function than to
239 call it and ignore errors. */ 236 call it and ignore errors. */
240 do_sigaltstack(&st, NULL, regs->r1); 237 if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->r1))
238 goto badframe;
241 239
242 return rval; 240 return rval;
243 241
@@ -251,7 +249,7 @@ badframe:
251 */ 249 */
252 250
253static int 251static int
254setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, 252setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
255 unsigned long mask) 253 unsigned long mask)
256{ 254{
257 int err = 0; 255 int err = 0;
@@ -278,7 +276,7 @@ setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
278/* 276/*
279 * Determine which stack to use.. 277 * Determine which stack to use..
280 */ 278 */
281static inline void * 279static inline void __user *
282get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) 280get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
283{ 281{
284 /* Default to using normal stack */ 282 /* Default to using normal stack */
@@ -287,87 +285,13 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
287 if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && !on_sig_stack(sp)) 285 if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && !on_sig_stack(sp))
288 sp = current->sas_ss_sp + current->sas_ss_size; 286 sp = current->sas_ss_sp + current->sas_ss_size;
289 287
290 return (void *)((sp - frame_size) & -8UL); 288 return (void __user *)((sp - frame_size) & -8UL);
291}
292
293static void setup_frame(int sig, struct k_sigaction *ka,
294 sigset_t *set, struct pt_regs *regs)
295{
296 struct sigframe *frame;
297 int err = 0;
298 int signal;
299
300 frame = get_sigframe(ka, regs, sizeof(*frame));
301
302 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
303 goto give_sigsegv;
304
305 signal = current_thread_info()->exec_domain
306 && current_thread_info()->exec_domain->signal_invmap
307 && sig < 32
308 ? current_thread_info()->exec_domain->signal_invmap[sig]
309 : sig;
310
311 err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
312
313 if (_NSIG_WORDS > 1) {
314 err |= __copy_to_user(frame->extramask, &set->sig[1],
315 sizeof(frame->extramask));
316 }
317
318 /* Set up to return from userspace. If provided, use a stub
319 already in userspace. */
320 /* minus 8 is offset to cater for "rtsd r15,8" offset */
321 if (ka->sa.sa_flags & SA_RESTORER) {
322 regs->r15 = ((unsigned long)ka->sa.sa_restorer)-8;
323 } else {
324 /* Note, these encodings are _big endian_! */
325
326 /* addi r12, r0, __NR_sigreturn */
327 err |= __put_user(0x31800000 | __NR_sigreturn ,
328 frame->tramp + 0);
329 /* brki r14, 0x8 */
330 err |= __put_user(0xb9cc0008, frame->tramp + 1);
331
332 /* Return from sighandler will jump to the tramp.
333 Negative 8 offset because return is rtsd r15, 8 */
334 regs->r15 = ((unsigned long)frame->tramp)-8;
335
336 __invalidate_cache_sigtramp((unsigned long)frame->tramp);
337 }
338
339 if (err)
340 goto give_sigsegv;
341
342 /* Set up registers for signal handler */
343 regs->r1 = (unsigned long) frame - STATE_SAVE_ARG_SPACE;
344
345 /* Signal handler args: */
346 regs->r5 = signal; /* Arg 0: signum */
347 regs->r6 = (unsigned long) &frame->sc; /* arg 1: sigcontext */
348
349 /* Offset of 4 to handle microblaze rtid r14, 0 */
350 regs->pc = (unsigned long)ka->sa.sa_handler;
351
352 set_fs(USER_DS);
353
354#ifdef DEBUG_SIG
355 printk(KERN_INFO "SIG deliver (%s:%d): sp=%p pc=%08lx\n",
356 current->comm, current->pid, frame, regs->pc);
357#endif
358
359 return;
360
361give_sigsegv:
362 if (sig == SIGSEGV)
363 ka->sa.sa_handler = SIG_DFL;
364 force_sig(SIGSEGV, current);
365} 289}
366 290
367static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 291static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
368 sigset_t *set, struct pt_regs *regs) 292 sigset_t *set, struct pt_regs *regs)
369{ 293{
370 struct rt_sigframe *frame; 294 struct rt_sigframe __user *frame;
371 int err = 0; 295 int err = 0;
372 int signal; 296 int signal;
373 297
@@ -382,7 +306,8 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
382 ? current_thread_info()->exec_domain->signal_invmap[sig] 306 ? current_thread_info()->exec_domain->signal_invmap[sig]
383 : sig; 307 : sig;
384 308
385 err |= copy_siginfo_to_user(&frame->info, info); 309 if (info)
310 err |= copy_siginfo_to_user(&frame->info, info);
386 311
387 /* Create the ucontext. */ 312 /* Create the ucontext. */
388 err |= __put_user(0, &frame->uc.uc_flags); 313 err |= __put_user(0, &frame->uc.uc_flags);
@@ -463,7 +388,15 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
463 case -ERESTARTNOINTR: 388 case -ERESTARTNOINTR:
464do_restart: 389do_restart:
465 /* offset of 4 bytes to re-execute trap (brki) instruction */ 390 /* offset of 4 bytes to re-execute trap (brki) instruction */
391#ifndef CONFIG_MMU
466 regs->pc -= 4; 392 regs->pc -= 4;
393#else
394 /* offset of 8 bytes required = 4 for rtbd
395 offset, plus 4 for size of
396 "brki r14,8"
397 instruction. */
398 regs->pc -= 8;
399#endif
467 break; 400 break;
468 } 401 }
469} 402}
@@ -480,7 +413,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
480 if (ka->sa.sa_flags & SA_SIGINFO) 413 if (ka->sa.sa_flags & SA_SIGINFO)
481 setup_rt_frame(sig, ka, info, oldset, regs); 414 setup_rt_frame(sig, ka, info, oldset, regs);
482 else 415 else
483 setup_frame(sig, ka, oldset, regs); 416 setup_rt_frame(sig, ka, NULL, oldset, regs);
484 417
485 if (ka->sa.sa_flags & SA_ONESHOT) 418 if (ka->sa.sa_flags & SA_ONESHOT)
486 ka->sa.sa_handler = SIG_DFL; 419 ka->sa.sa_handler = SIG_DFL;