Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / arch / riscv / kernel / signal.c
index d0f6f21..17ba190 100644 (file)
 #include <asm/switch_to.h>
 #include <asm/csr.h>
 
+extern u32 __user_rt_sigreturn[2];
+
 #define DEBUG_SIG 0
 
 struct rt_sigframe {
        struct siginfo info;
        struct ucontext uc;
+#ifndef CONFIG_MMU
+       u32 sigreturn_code[2];
+#endif
 };
 
 #ifdef CONFIG_FPU
@@ -124,7 +129,7 @@ badframe:
                pr_info_ratelimited(
                        "%s[%d]: bad frame in %s: frame=%p pc=%p sp=%p\n",
                        task->comm, task_pid_nr(task), __func__,
-                       frame, (void *)regs->sepc, (void *)regs->sp);
+                       frame, (void *)regs->epc, (void *)regs->sp);
        }
        force_sig(SIGSEGV);
        return 0;
@@ -166,7 +171,6 @@ static inline void __user *get_sigframe(struct ksignal *ksig,
        return (void __user *)sp;
 }
 
-
 static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
        struct pt_regs *regs)
 {
@@ -189,8 +193,19 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
                return -EFAULT;
 
        /* Set up to return from userspace. */
+#ifdef CONFIG_MMU
        regs->ra = (unsigned long)VDSO_SYMBOL(
                current->mm->context.vdso, rt_sigreturn);
+#else
+       /*
+        * For the nommu case we don't have a VDSO.  Instead we push two
+        * instructions to call the rt_sigreturn syscall onto the user stack.
+        */
+       if (copy_to_user(&frame->sigreturn_code, __user_rt_sigreturn,
+                        sizeof(frame->sigreturn_code)))
+               return -EFAULT;
+       regs->ra = (unsigned long)&frame->sigreturn_code;
+#endif /* CONFIG_MMU */
 
        /*
         * Set up registers for signal handler.
@@ -199,7 +214,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
         * We always pass siginfo and mcontext, regardless of SA_SIGINFO,
         * since some things rely on this (e.g. glibc's debug/segfault.c).
         */
-       regs->sepc = (unsigned long)ksig->ka.sa.sa_handler;
+       regs->epc = (unsigned long)ksig->ka.sa.sa_handler;
        regs->sp = (unsigned long)frame;
        regs->a0 = ksig->sig;                     /* a0: signal number */
        regs->a1 = (unsigned long)(&frame->info); /* a1: siginfo pointer */
@@ -208,7 +223,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
 #if DEBUG_SIG
        pr_info("SIG deliver (%s:%d): sig=%d pc=%p ra=%p sp=%p\n",
                current->comm, task_pid_nr(current), ksig->sig,
-               (void *)regs->sepc, (void *)regs->ra, frame);
+               (void *)regs->epc, (void *)regs->ra, frame);
 #endif
 
        return 0;
@@ -220,10 +235,9 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
        int ret;
 
        /* Are we from a system call? */
-       if (regs->scause == EXC_SYSCALL) {
+       if (regs->cause == EXC_SYSCALL) {
                /* Avoid additional syscall restarting via ret_from_exception */
-               regs->scause = -1UL;
-
+               regs->cause = -1UL;
                /* If so, check system call restarting.. */
                switch (regs->a0) {
                case -ERESTART_RESTARTBLOCK:
@@ -239,7 +253,7 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
                        /* fallthrough */
                case -ERESTARTNOINTR:
                         regs->a0 = regs->orig_a0;
-                       regs->sepc -= 0x4;
+                       regs->epc -= 0x4;
                        break;
                }
        }
@@ -261,9 +275,9 @@ static void do_signal(struct pt_regs *regs)
        }
 
        /* Did we come from a system call? */
-       if (regs->scause == EXC_SYSCALL) {
+       if (regs->cause == EXC_SYSCALL) {
                /* Avoid additional syscall restarting via ret_from_exception */
-               regs->scause = -1UL;
+               regs->cause = -1UL;
 
                /* Restart the system call - no handlers present */
                switch (regs->a0) {
@@ -271,12 +285,12 @@ static void do_signal(struct pt_regs *regs)
                case -ERESTARTSYS:
                case -ERESTARTNOINTR:
                         regs->a0 = regs->orig_a0;
-                       regs->sepc -= 0x4;
+                       regs->epc -= 0x4;
                        break;
                case -ERESTART_RESTARTBLOCK:
                         regs->a0 = regs->orig_a0;
                        regs->a7 = __NR_restart_syscall;
-                       regs->sepc -= 0x4;
+                       regs->epc -= 0x4;
                        break;
                }
        }