aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel/signal_32.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/kernel/signal_32.c')
-rw-r--r--arch/sh/kernel/signal_32.c36
1 files changed, 25 insertions, 11 deletions
diff --git a/arch/sh/kernel/signal_32.c b/arch/sh/kernel/signal_32.c
index f311551d9a0..4bbbde895a5 100644
--- a/arch/sh/kernel/signal_32.c
+++ b/arch/sh/kernel/signal_32.c
@@ -33,6 +33,11 @@
33 33
34#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 34#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
35 35
36struct fdpic_func_descriptor {
37 unsigned long text;
38 unsigned long GOT;
39};
40
36/* 41/*
37 * Atomically swap in the new signal mask, and wait for a signal. 42 * Atomically swap in the new signal mask, and wait for a signal.
38 */ 43 */
@@ -368,6 +373,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
368 err |= __put_user(OR_R0_R0, &frame->retcode[6]); 373 err |= __put_user(OR_R0_R0, &frame->retcode[6]);
369 err |= __put_user((__NR_sigreturn), &frame->retcode[7]); 374 err |= __put_user((__NR_sigreturn), &frame->retcode[7]);
370 regs->pr = (unsigned long) frame->retcode; 375 regs->pr = (unsigned long) frame->retcode;
376 flush_icache_range(regs->pr, regs->pr + sizeof(frame->retcode));
371 } 377 }
372 378
373 if (err) 379 if (err)
@@ -378,18 +384,21 @@ static int setup_frame(int sig, struct k_sigaction *ka,
378 regs->regs[4] = signal; /* Arg for signal handler */ 384 regs->regs[4] = signal; /* Arg for signal handler */
379 regs->regs[5] = 0; 385 regs->regs[5] = 0;
380 regs->regs[6] = (unsigned long) &frame->sc; 386 regs->regs[6] = (unsigned long) &frame->sc;
381 regs->pc = (unsigned long) ka->sa.sa_handler; 387
388 if (current->personality & FDPIC_FUNCPTRS) {
389 struct fdpic_func_descriptor __user *funcptr =
390 (struct fdpic_func_descriptor __user *)ka->sa.sa_handler;
391
392 __get_user(regs->pc, &funcptr->text);
393 __get_user(regs->regs[12], &funcptr->GOT);
394 } else
395 regs->pc = (unsigned long)ka->sa.sa_handler;
382 396
383 set_fs(USER_DS); 397 set_fs(USER_DS);
384 398
385 pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n", 399 pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
386 current->comm, task_pid_nr(current), frame, regs->pc, regs->pr); 400 current->comm, task_pid_nr(current), frame, regs->pc, regs->pr);
387 401
388 flush_cache_sigtramp(regs->pr);
389
390 if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode))
391 flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES);
392
393 return 0; 402 return 0;
394 403
395give_sigsegv: 404give_sigsegv:
@@ -458,17 +467,22 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
458 regs->regs[4] = signal; /* Arg for signal handler */ 467 regs->regs[4] = signal; /* Arg for signal handler */
459 regs->regs[5] = (unsigned long) &frame->info; 468 regs->regs[5] = (unsigned long) &frame->info;
460 regs->regs[6] = (unsigned long) &frame->uc; 469 regs->regs[6] = (unsigned long) &frame->uc;
461 regs->pc = (unsigned long) ka->sa.sa_handler; 470
471 if (current->personality & FDPIC_FUNCPTRS) {
472 struct fdpic_func_descriptor __user *funcptr =
473 (struct fdpic_func_descriptor __user *)ka->sa.sa_handler;
474
475 __get_user(regs->pc, &funcptr->text);
476 __get_user(regs->regs[12], &funcptr->GOT);
477 } else
478 regs->pc = (unsigned long)ka->sa.sa_handler;
462 479
463 set_fs(USER_DS); 480 set_fs(USER_DS);
464 481
465 pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n", 482 pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
466 current->comm, task_pid_nr(current), frame, regs->pc, regs->pr); 483 current->comm, task_pid_nr(current), frame, regs->pc, regs->pr);
467 484
468 flush_cache_sigtramp(regs->pr); 485 flush_icache_range(regs->pr, regs->pr + sizeof(frame->retcode));
469
470 if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode))
471 flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES);
472 486
473 return 0; 487 return 0;
474 488