···11+/*22+ * Copyright Altera Corporation (C) 2013. All rights reserved33+ *44+ * This program is free software; you can redistribute it and/or modify it55+ * under the terms and conditions of the GNU General Public License,66+ * version 2, as published by the Free Software Foundation.77+ *88+ * This program is distributed in the hope it will be useful, but WITHOUT99+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or1010+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for1111+ * more details.1212+ *1313+ * You should have received a copy of the GNU General Public License along with1414+ * this program. If not, see <http://www.gnu.org/licenses/>.1515+ *1616+ */1717+#ifndef _NIOS2_SIGNAL_H1818+#define _NIOS2_SIGNAL_H1919+2020+#include <uapi/asm/signal.h>2121+2222+#endif /* _NIOS2_SIGNAL_H */
+32
arch/nios2/include/asm/ucontext.h
···11+/*22+ * Copyright (C) 2010 Tobias Klauser <tklauser@distanz.ch>33+ * Copyright (C) 2004 Microtronix Datacom Ltd44+ *55+ * This file is subject to the terms and conditions of the GNU General Public66+ * License. See the file "COPYING" in the main directory of this archive77+ * for more details.88+ */99+1010+#ifndef _ASM_NIOS2_UCONTEXT_H1111+#define _ASM_NIOS2_UCONTEXT_H1212+1313+typedef int greg_t;1414+#define NGREG 321515+typedef greg_t gregset_t[NGREG];1616+1717+struct mcontext {1818+ int version;1919+ gregset_t gregs;2020+};2121+2222+#define MCONTEXT_VERSION 22323+2424+struct ucontext {2525+ unsigned long uc_flags;2626+ struct ucontext *uc_link;2727+ stack_t uc_stack;2828+ struct mcontext uc_mcontext;2929+ sigset_t uc_sigmask; /* mask last for extensibility */3030+};3131+3232+#endif
+28
arch/nios2/include/uapi/asm/sigcontext.h
···11+/*22+ * Copyright (C) 2004, Microtronix Datacom Ltd.33+ *44+ * All rights reserved.55+ *66+ * This program is free software; you can redistribute it and/or modify77+ * it under the terms of the GNU General Public License as published by88+ * the Free Software Foundation; either version 2 of the License, or99+ * (at your option) any later version.1010+ *1111+ * This program is distributed in the hope that it will be useful, but1212+ * WITHOUT ANY WARRANTY; without even the implied warranty of1313+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or1414+ * NON INFRINGEMENT. See the GNU General Public License for more1515+ * details.1616+ */1717+1818+#ifndef _ASM_NIOS2_SIGCONTEXT_H1919+#define _ASM_NIOS2_SIGCONTEXT_H2020+2121+#include <asm/ptrace.h>2222+2323+struct sigcontext {2424+ struct pt_regs regs;2525+ unsigned long sc_mask; /* old sigmask */2626+};2727+2828+#endif
+23
arch/nios2/include/uapi/asm/signal.h
···11+/*22+ * Copyright Altera Corporation (C) 2013. All rights reserved33+ *44+ * This program is free software; you can redistribute it and/or modify it55+ * under the terms and conditions of the GNU General Public License,66+ * version 2, as published by the Free Software Foundation.77+ *88+ * This program is distributed in the hope it will be useful, but WITHOUT99+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or1010+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for1111+ * more details.1212+ *1313+ * You should have received a copy of the GNU General Public License along with1414+ * this program. If not, see <http://www.gnu.org/licenses/>.1515+ *1616+ */1717+#ifndef _ASM_NIOS2_SIGNAL_H1818+#define _ASM_NIOS2_SIGNAL_H1919+2020+#define SA_RESTORER 0x040000002121+#include <asm-generic/signal.h>2222+2323+#endif /* _ASM_NIOS2_SIGNAL_H */
+323
arch/nios2/kernel/signal.c
···11+/*22+ * Copyright (C) 2013-2014 Altera Corporation33+ * Copyright (C) 2011-2012 Tobias Klauser <tklauser@distanz.ch>44+ * Copyright (C) 2004 Microtronix Datacom Ltd55+ * Copyright (C) 1991, 1992 Linus Torvalds66+ *77+ * This file is subject to the terms and conditions of the GNU General Public88+ * License. See the file COPYING in the main directory of this archive99+ * for more details.1010+ */1111+1212+#include <linux/signal.h>1313+#include <linux/errno.h>1414+#include <linux/ptrace.h>1515+#include <linux/uaccess.h>1616+#include <linux/unistd.h>1717+#include <linux/personality.h>1818+#include <linux/tracehook.h>1919+2020+#include <asm/ucontext.h>2121+#include <asm/cacheflush.h>2222+2323+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))2424+2525+/*2626+ * Do a signal return; undo the signal stack.2727+ *2828+ * Keep the return code on the stack quadword aligned!2929+ * That makes the cache flush below easier.3030+ */3131+3232+struct rt_sigframe {3333+ struct siginfo info;3434+ struct ucontext uc;3535+};3636+3737+static inline int rt_restore_ucontext(struct pt_regs *regs,3838+ struct switch_stack *sw,3939+ struct ucontext *uc, int *pr2)4040+{4141+ int temp;4242+ greg_t *gregs = uc->uc_mcontext.gregs;4343+ int err;4444+4545+ /* Always make any pending restarted system calls return -EINTR */4646+ current_thread_info()->restart_block.fn = do_no_restart_syscall;4747+4848+ err = __get_user(temp, &uc->uc_mcontext.version);4949+ if (temp != MCONTEXT_VERSION)5050+ goto badframe;5151+ /* restore passed registers */5252+ err |= __get_user(regs->r1, &gregs[0]);5353+ err |= __get_user(regs->r2, &gregs[1]);5454+ err |= __get_user(regs->r3, &gregs[2]);5555+ err |= __get_user(regs->r4, &gregs[3]);5656+ err |= __get_user(regs->r5, &gregs[4]);5757+ err |= __get_user(regs->r6, &gregs[5]);5858+ err |= __get_user(regs->r7, &gregs[6]);5959+ err |= __get_user(regs->r8, &gregs[7]);6060+ err |= __get_user(regs->r9, &gregs[8]);6161+ err |= __get_user(regs->r10, &gregs[9]);6262+ err |= __get_user(regs->r11, &gregs[10]);6363+ err |= __get_user(regs->r12, &gregs[11]);6464+ err |= __get_user(regs->r13, &gregs[12]);6565+ err |= __get_user(regs->r14, &gregs[13]);6666+ err |= __get_user(regs->r15, &gregs[14]);6767+ err |= __get_user(sw->r16, &gregs[15]);6868+ err |= __get_user(sw->r17, &gregs[16]);6969+ err |= __get_user(sw->r18, &gregs[17]);7070+ err |= __get_user(sw->r19, &gregs[18]);7171+ err |= __get_user(sw->r20, &gregs[19]);7272+ err |= __get_user(sw->r21, &gregs[20]);7373+ err |= __get_user(sw->r22, &gregs[21]);7474+ err |= __get_user(sw->r23, &gregs[22]);7575+ /* gregs[23] is handled below */7676+ err |= __get_user(sw->fp, &gregs[24]); /* Verify, should this be7777+ settable */7878+ err |= __get_user(sw->gp, &gregs[25]); /* Verify, should this be7979+ settable */8080+8181+ err |= __get_user(temp, &gregs[26]); /* Not really necessary no user8282+ settable bits */8383+ err |= __get_user(regs->ea, &gregs[27]);8484+8585+ err |= __get_user(regs->ra, &gregs[23]);8686+ err |= __get_user(regs->sp, &gregs[28]);8787+8888+ regs->orig_r2 = -1; /* disable syscall checks */8989+9090+ err |= restore_altstack(&uc->uc_stack);9191+ if (err)9292+ goto badframe;9393+9494+ *pr2 = regs->r2;9595+ return err;9696+9797+badframe:9898+ return 1;9999+}100100+101101+asmlinkage int do_rt_sigreturn(struct switch_stack *sw)102102+{103103+ struct pt_regs *regs = (struct pt_regs *)(sw + 1);104104+ /* Verify, can we follow the stack back */105105+ struct rt_sigframe *frame = (struct rt_sigframe *) regs->sp;106106+ sigset_t set;107107+ int rval;108108+109109+ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))110110+ goto badframe;111111+112112+ if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))113113+ goto badframe;114114+115115+ set_current_blocked(&set);116116+117117+ if (rt_restore_ucontext(regs, sw, &frame->uc, &rval))118118+ goto badframe;119119+120120+ return rval;121121+122122+badframe:123123+ force_sig(SIGSEGV, current);124124+ return 0;125125+}126126+127127+static inline int rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs)128128+{129129+ struct switch_stack *sw = (struct switch_stack *)regs - 1;130130+ greg_t *gregs = uc->uc_mcontext.gregs;131131+ int err = 0;132132+133133+ err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version);134134+ err |= __put_user(regs->r1, &gregs[0]);135135+ err |= __put_user(regs->r2, &gregs[1]);136136+ err |= __put_user(regs->r3, &gregs[2]);137137+ err |= __put_user(regs->r4, &gregs[3]);138138+ err |= __put_user(regs->r5, &gregs[4]);139139+ err |= __put_user(regs->r6, &gregs[5]);140140+ err |= __put_user(regs->r7, &gregs[6]);141141+ err |= __put_user(regs->r8, &gregs[7]);142142+ err |= __put_user(regs->r9, &gregs[8]);143143+ err |= __put_user(regs->r10, &gregs[9]);144144+ err |= __put_user(regs->r11, &gregs[10]);145145+ err |= __put_user(regs->r12, &gregs[11]);146146+ err |= __put_user(regs->r13, &gregs[12]);147147+ err |= __put_user(regs->r14, &gregs[13]);148148+ err |= __put_user(regs->r15, &gregs[14]);149149+ err |= __put_user(sw->r16, &gregs[15]);150150+ err |= __put_user(sw->r17, &gregs[16]);151151+ err |= __put_user(sw->r18, &gregs[17]);152152+ err |= __put_user(sw->r19, &gregs[18]);153153+ err |= __put_user(sw->r20, &gregs[19]);154154+ err |= __put_user(sw->r21, &gregs[20]);155155+ err |= __put_user(sw->r22, &gregs[21]);156156+ err |= __put_user(sw->r23, &gregs[22]);157157+ err |= __put_user(regs->ra, &gregs[23]);158158+ err |= __put_user(sw->fp, &gregs[24]);159159+ err |= __put_user(sw->gp, &gregs[25]);160160+ err |= __put_user(regs->ea, &gregs[27]);161161+ err |= __put_user(regs->sp, &gregs[28]);162162+ return err;163163+}164164+165165+static inline void *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,166166+ size_t frame_size)167167+{168168+ unsigned long usp;169169+170170+ /* Default to using normal stack. */171171+ usp = regs->sp;172172+173173+ /* This is the X/Open sanctioned signal stack switching. */174174+ usp = sigsp(usp, ksig);175175+176176+ /* Verify, is it 32 or 64 bit aligned */177177+ return (void *)((usp - frame_size) & -8UL);178178+}179179+180180+static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,181181+ struct pt_regs *regs)182182+{183183+ struct rt_sigframe *frame;184184+ int err = 0;185185+186186+ frame = get_sigframe(ksig, regs, sizeof(*frame));187187+188188+ if (ksig->ka.sa.sa_flags & SA_SIGINFO)189189+ err |= copy_siginfo_to_user(&frame->info, &ksig->info);190190+191191+ /* Create the ucontext. */192192+ err |= __put_user(0, &frame->uc.uc_flags);193193+ err |= __put_user(0, &frame->uc.uc_link);194194+ err |= __save_altstack(&frame->uc.uc_stack, regs->sp);195195+ err |= rt_setup_ucontext(&frame->uc, regs);196196+ err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));197197+198198+ if (err)199199+ goto give_sigsegv;200200+201201+ /* Set up to return from userspace; jump to fixed address sigreturn202202+ trampoline on kuser page. */203203+ regs->ra = (unsigned long) (0x1040);204204+205205+ /* Set up registers for signal handler */206206+ regs->sp = (unsigned long) frame;207207+ regs->r4 = (unsigned long) ksig->sig;208208+ regs->r5 = (unsigned long) &frame->info;209209+ regs->r6 = (unsigned long) &frame->uc;210210+ regs->ea = (unsigned long) ksig->ka.sa.sa_handler;211211+ return 0;212212+213213+give_sigsegv:214214+ force_sigsegv(ksig->sig, current);215215+ return -EFAULT;216216+}217217+218218+/*219219+ * OK, we're invoking a handler220220+ */221221+static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)222222+{223223+ int ret;224224+ sigset_t *oldset = sigmask_to_save();225225+226226+ /* set up the stack frame */227227+ ret = setup_rt_frame(ksig, oldset, regs);228228+229229+ signal_setup_done(ret, ksig, 0);230230+}231231+232232+static int do_signal(struct pt_regs *regs)233233+{234234+ unsigned int retval = 0, continue_addr = 0, restart_addr = 0;235235+ int restart = 0;236236+ struct ksignal ksig;237237+238238+ current->thread.kregs = regs;239239+240240+ /*241241+ * If we were from a system call, check for system call restarting...242242+ */243243+ if (regs->orig_r2 >= 0) {244244+ continue_addr = regs->ea;245245+ restart_addr = continue_addr - 4;246246+ retval = regs->r2;247247+248248+ /*249249+ * Prepare for system call restart. We do this here so that a250250+ * debugger will see the already changed PC.251251+ */252252+ switch (retval) {253253+ case ERESTART_RESTARTBLOCK:254254+ restart = -2;255255+ case ERESTARTNOHAND:256256+ case ERESTARTSYS:257257+ case ERESTARTNOINTR:258258+ restart++;259259+ regs->r2 = regs->orig_r2;260260+ regs->r7 = regs->orig_r7;261261+ regs->ea = restart_addr;262262+ break;263263+ }264264+ }265265+266266+ if (get_signal(&ksig)) {267267+ /* handler */268268+ if (unlikely(restart && regs->ea == restart_addr)) {269269+ if (retval == ERESTARTNOHAND ||270270+ retval == ERESTART_RESTARTBLOCK ||271271+ (retval == ERESTARTSYS272272+ && !(ksig.ka.sa.sa_flags & SA_RESTART))) {273273+ regs->r2 = EINTR;274274+ regs->r7 = 1;275275+ regs->ea = continue_addr;276276+ }277277+ }278278+ handle_signal(&ksig, regs);279279+ return 0;280280+ }281281+282282+ /*283283+ * No handler present284284+ */285285+ if (unlikely(restart) && regs->ea == restart_addr) {286286+ regs->ea = continue_addr;287287+ regs->r2 = __NR_restart_syscall;288288+ }289289+290290+ /*291291+ * If there's no signal to deliver, we just put the saved sigmask back.292292+ */293293+ restore_saved_sigmask();294294+295295+ return restart;296296+}297297+298298+asmlinkage int do_notify_resume(struct pt_regs *regs)299299+{300300+ /*301301+ * We want the common case to go fast, which is why we may in certain302302+ * cases get here from kernel mode. Just return without doing anything303303+ * if so.304304+ */305305+ if (!user_mode(regs))306306+ return 0;307307+308308+ if (test_thread_flag(TIF_SIGPENDING)) {309309+ int restart = do_signal(regs);310310+311311+ if (unlikely(restart)) {312312+ /*313313+ * Restart without handlers.314314+ * Deal with it without leaving315315+ * the kernel space.316316+ */317317+ return restart;318318+ }319319+ } else if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME))320320+ tracehook_notify_resume(regs);321321+322322+ return 0;323323+}