1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2c3581039SVineet Gupta /*
3c3581039SVineet Gupta * Signal Handling for ARC
4c3581039SVineet Gupta *
5c3581039SVineet Gupta * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
6c3581039SVineet Gupta *
7c3581039SVineet Gupta * vineetg: Jan 2010 (Restarting of timer related syscalls)
8c3581039SVineet Gupta *
9c3581039SVineet Gupta * vineetg: Nov 2009 (Everything needed for TIF_RESTORE_SIGMASK)
10c3581039SVineet Gupta * -do_signal() supports TIF_RESTORE_SIGMASK
11c3581039SVineet Gupta * -do_signal() no loner needs oldset, required by OLD sys_sigsuspend
12c3581039SVineet Gupta * -sys_rt_sigsuspend() now comes from generic code, so discard arch implemen
13c3581039SVineet Gupta * -sys_sigsuspend() no longer needs to fudge ptregs, hence that arg removed
14c3581039SVineet Gupta * -sys_sigsuspend() no longer loops for do_signal(), sets TIF_xxx and leaves
15c3581039SVineet Gupta * the job to do_signal()
16c3581039SVineet Gupta *
17c3581039SVineet Gupta * vineetg: July 2009
18c3581039SVineet Gupta * -Modified Code to support the uClibc provided userland sigreturn stub
19c3581039SVineet Gupta * to avoid kernel synthesing it on user stack at runtime, costing TLB
20c3581039SVineet Gupta * probes and Cache line flushes.
21c3581039SVineet Gupta *
22c3581039SVineet Gupta * vineetg: July 2009
23c3581039SVineet Gupta * -In stash_usr_regs( ) and restore_usr_regs( ), save/restore of user regs
24c3581039SVineet Gupta * in done in block copy rather than one word at a time.
25c3581039SVineet Gupta * This saves around 2K of code and improves LMBench lat_sig <catch>
26c3581039SVineet Gupta *
27c3581039SVineet Gupta * rajeshwarr: Feb 2009
28c3581039SVineet Gupta * - Support for Realtime Signals
29c3581039SVineet Gupta *
30c3581039SVineet Gupta * vineetg: Aug 11th 2008: Bug #94183
31c3581039SVineet Gupta * -ViXS were still seeing crashes when using insmod to load drivers.
32c3581039SVineet Gupta * It turned out that the code to change Execute permssions for TLB entries
33c3581039SVineet Gupta * of user was not guarded for interrupts (mod_tlb_permission)
342547476aSAndrea Gelmini * This was causing TLB entries to be overwritten on unrelated indexes
35c3581039SVineet Gupta *
36c3581039SVineet Gupta * Vineetg: July 15th 2008: Bug #94183
37c3581039SVineet Gupta * -Exception happens in Delay slot of a JMP, and before user space resumes,
38c3581039SVineet Gupta * Signal is delivered (Ctrl + C) = >SIGINT.
39c3581039SVineet Gupta * setup_frame( ) sets up PC,SP,BLINK to enable user space signal handler
40c3581039SVineet Gupta * to run, but doesn't clear the Delay slot bit from status32. As a result,
41c3581039SVineet Gupta * on resuming user mode, signal handler branches off to BTA of orig JMP
42c3581039SVineet Gupta * -FIX: clear the DE bit from status32 in setup_frame( )
43c3581039SVineet Gupta *
44c3581039SVineet Gupta * Rahul Trivedi, Kanika Nema: Codito Technologies 2004
45c3581039SVineet Gupta */
46c3581039SVineet Gupta
47c3581039SVineet Gupta #include <linux/signal.h>
48c3581039SVineet Gupta #include <linux/ptrace.h>
49c3581039SVineet Gupta #include <linux/personality.h>
50c3581039SVineet Gupta #include <linux/uaccess.h>
51c3581039SVineet Gupta #include <linux/syscalls.h>
5203248addSEric W. Biederman #include <linux/resume_user_mode.h>
5368db0cf1SIngo Molnar #include <linux/sched/task_stack.h>
5468db0cf1SIngo Molnar
55c3581039SVineet Gupta #include <asm/ucontext.h>
564d369680SVineet Gupta #include <asm/entry.h>
57c3581039SVineet Gupta
58c3581039SVineet Gupta struct rt_sigframe {
59c3581039SVineet Gupta struct siginfo info;
60c3581039SVineet Gupta struct ucontext uc;
61c3581039SVineet Gupta #define MAGIC_SIGALTSTK 0x07302004
62c3581039SVineet Gupta unsigned int sigret_magic;
63c3581039SVineet Gupta };
64c3581039SVineet Gupta
save_arcv2_regs(struct sigcontext __user * mctx,struct pt_regs * regs)65*358bca0bSVineet Gupta static int save_arcv2_regs(struct sigcontext __user *mctx, struct pt_regs *regs)
6696f1b001SVineet Gupta {
6796f1b001SVineet Gupta int err = 0;
6896f1b001SVineet Gupta #ifndef CONFIG_ISA_ARCOMPACT
6996f1b001SVineet Gupta struct user_regs_arcv2 v2abi;
7096f1b001SVineet Gupta
7196f1b001SVineet Gupta v2abi.r30 = regs->r30;
7296f1b001SVineet Gupta #ifdef CONFIG_ARC_HAS_ACCL_REGS
7396f1b001SVineet Gupta v2abi.r58 = regs->r58;
7496f1b001SVineet Gupta v2abi.r59 = regs->r59;
7596f1b001SVineet Gupta #else
7696f1b001SVineet Gupta v2abi.r58 = v2abi.r59 = 0;
7796f1b001SVineet Gupta #endif
78*358bca0bSVineet Gupta err = __copy_to_user(&mctx->v2abi, (void const *)&v2abi, sizeof(v2abi));
7996f1b001SVineet Gupta #endif
8096f1b001SVineet Gupta return err;
8196f1b001SVineet Gupta }
8296f1b001SVineet Gupta
restore_arcv2_regs(struct sigcontext __user * mctx,struct pt_regs * regs)83*358bca0bSVineet Gupta static int restore_arcv2_regs(struct sigcontext __user *mctx, struct pt_regs *regs)
8496f1b001SVineet Gupta {
8596f1b001SVineet Gupta int err = 0;
8696f1b001SVineet Gupta #ifndef CONFIG_ISA_ARCOMPACT
8796f1b001SVineet Gupta struct user_regs_arcv2 v2abi;
8896f1b001SVineet Gupta
8996f1b001SVineet Gupta err = __copy_from_user(&v2abi, &mctx->v2abi, sizeof(v2abi));
9096f1b001SVineet Gupta
9196f1b001SVineet Gupta regs->r30 = v2abi.r30;
9296f1b001SVineet Gupta #ifdef CONFIG_ARC_HAS_ACCL_REGS
9396f1b001SVineet Gupta regs->r58 = v2abi.r58;
9496f1b001SVineet Gupta regs->r59 = v2abi.r59;
9596f1b001SVineet Gupta #endif
9696f1b001SVineet Gupta #endif
9796f1b001SVineet Gupta return err;
9896f1b001SVineet Gupta }
9996f1b001SVineet Gupta
100c3581039SVineet Gupta static int
stash_usr_regs(struct rt_sigframe __user * sf,struct pt_regs * regs,sigset_t * set)101c3581039SVineet Gupta stash_usr_regs(struct rt_sigframe __user *sf, struct pt_regs *regs,
102c3581039SVineet Gupta sigset_t *set)
103c3581039SVineet Gupta {
104c3581039SVineet Gupta int err;
1056ffb9c8cSVineet Gupta struct user_regs_struct uregs;
1066ffb9c8cSVineet Gupta
1076ffb9c8cSVineet Gupta uregs.scratch.bta = regs->bta;
1086ffb9c8cSVineet Gupta uregs.scratch.lp_start = regs->lp_start;
1096ffb9c8cSVineet Gupta uregs.scratch.lp_end = regs->lp_end;
1106ffb9c8cSVineet Gupta uregs.scratch.lp_count = regs->lp_count;
1116ffb9c8cSVineet Gupta uregs.scratch.status32 = regs->status32;
1126ffb9c8cSVineet Gupta uregs.scratch.ret = regs->ret;
1136ffb9c8cSVineet Gupta uregs.scratch.blink = regs->blink;
1146ffb9c8cSVineet Gupta uregs.scratch.fp = regs->fp;
1156ffb9c8cSVineet Gupta uregs.scratch.gp = regs->r26;
1166ffb9c8cSVineet Gupta uregs.scratch.r12 = regs->r12;
1176ffb9c8cSVineet Gupta uregs.scratch.r11 = regs->r11;
1186ffb9c8cSVineet Gupta uregs.scratch.r10 = regs->r10;
1196ffb9c8cSVineet Gupta uregs.scratch.r9 = regs->r9;
1206ffb9c8cSVineet Gupta uregs.scratch.r8 = regs->r8;
1216ffb9c8cSVineet Gupta uregs.scratch.r7 = regs->r7;
1226ffb9c8cSVineet Gupta uregs.scratch.r6 = regs->r6;
1236ffb9c8cSVineet Gupta uregs.scratch.r5 = regs->r5;
1246ffb9c8cSVineet Gupta uregs.scratch.r4 = regs->r4;
1256ffb9c8cSVineet Gupta uregs.scratch.r3 = regs->r3;
1266ffb9c8cSVineet Gupta uregs.scratch.r2 = regs->r2;
1276ffb9c8cSVineet Gupta uregs.scratch.r1 = regs->r1;
1286ffb9c8cSVineet Gupta uregs.scratch.r0 = regs->r0;
1296ffb9c8cSVineet Gupta uregs.scratch.sp = regs->sp;
1306ffb9c8cSVineet Gupta
1316ffb9c8cSVineet Gupta err = __copy_to_user(&(sf->uc.uc_mcontext.regs.scratch), &uregs.scratch,
132c3581039SVineet Gupta sizeof(sf->uc.uc_mcontext.regs.scratch));
13396f1b001SVineet Gupta
13496f1b001SVineet Gupta if (is_isa_arcv2())
13596f1b001SVineet Gupta err |= save_arcv2_regs(&(sf->uc.uc_mcontext), regs);
13696f1b001SVineet Gupta
137c3581039SVineet Gupta err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(sigset_t));
138c3581039SVineet Gupta
13946e15218SWang Qing return err ? -EFAULT : 0;
140c3581039SVineet Gupta }
141c3581039SVineet Gupta
restore_usr_regs(struct pt_regs * regs,struct rt_sigframe __user * sf)142c3581039SVineet Gupta static int restore_usr_regs(struct pt_regs *regs, struct rt_sigframe __user *sf)
143c3581039SVineet Gupta {
144c3581039SVineet Gupta sigset_t set;
145c3581039SVineet Gupta int err;
1466ffb9c8cSVineet Gupta struct user_regs_struct uregs;
147c3581039SVineet Gupta
148c3581039SVineet Gupta err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
1496ffb9c8cSVineet Gupta err |= __copy_from_user(&uregs.scratch,
1506ffb9c8cSVineet Gupta &(sf->uc.uc_mcontext.regs.scratch),
151c3581039SVineet Gupta sizeof(sf->uc.uc_mcontext.regs.scratch));
15296f1b001SVineet Gupta
15396f1b001SVineet Gupta if (is_isa_arcv2())
15496f1b001SVineet Gupta err |= restore_arcv2_regs(&(sf->uc.uc_mcontext), regs);
15596f1b001SVineet Gupta
1567798bf21SAl Viro if (err)
15746e15218SWang Qing return -EFAULT;
158c3581039SVineet Gupta
1597798bf21SAl Viro set_current_blocked(&set);
1606ffb9c8cSVineet Gupta regs->bta = uregs.scratch.bta;
1616ffb9c8cSVineet Gupta regs->lp_start = uregs.scratch.lp_start;
1626ffb9c8cSVineet Gupta regs->lp_end = uregs.scratch.lp_end;
1636ffb9c8cSVineet Gupta regs->lp_count = uregs.scratch.lp_count;
1646ffb9c8cSVineet Gupta regs->status32 = uregs.scratch.status32;
1656ffb9c8cSVineet Gupta regs->ret = uregs.scratch.ret;
1666ffb9c8cSVineet Gupta regs->blink = uregs.scratch.blink;
1676ffb9c8cSVineet Gupta regs->fp = uregs.scratch.fp;
1686ffb9c8cSVineet Gupta regs->r26 = uregs.scratch.gp;
1696ffb9c8cSVineet Gupta regs->r12 = uregs.scratch.r12;
1706ffb9c8cSVineet Gupta regs->r11 = uregs.scratch.r11;
1716ffb9c8cSVineet Gupta regs->r10 = uregs.scratch.r10;
1726ffb9c8cSVineet Gupta regs->r9 = uregs.scratch.r9;
1736ffb9c8cSVineet Gupta regs->r8 = uregs.scratch.r8;
1746ffb9c8cSVineet Gupta regs->r7 = uregs.scratch.r7;
1756ffb9c8cSVineet Gupta regs->r6 = uregs.scratch.r6;
1766ffb9c8cSVineet Gupta regs->r5 = uregs.scratch.r5;
1776ffb9c8cSVineet Gupta regs->r4 = uregs.scratch.r4;
1786ffb9c8cSVineet Gupta regs->r3 = uregs.scratch.r3;
1796ffb9c8cSVineet Gupta regs->r2 = uregs.scratch.r2;
1806ffb9c8cSVineet Gupta regs->r1 = uregs.scratch.r1;
1816ffb9c8cSVineet Gupta regs->r0 = uregs.scratch.r0;
1826ffb9c8cSVineet Gupta regs->sp = uregs.scratch.sp;
1836ffb9c8cSVineet Gupta
1847798bf21SAl Viro return 0;
185c3581039SVineet Gupta }
186c3581039SVineet Gupta
is_do_ss_needed(unsigned int magic)187c3581039SVineet Gupta static inline int is_do_ss_needed(unsigned int magic)
188c3581039SVineet Gupta {
189c3581039SVineet Gupta if (MAGIC_SIGALTSTK == magic)
190c3581039SVineet Gupta return 1;
191c3581039SVineet Gupta else
192c3581039SVineet Gupta return 0;
193c3581039SVineet Gupta }
194c3581039SVineet Gupta
SYSCALL_DEFINE0(rt_sigreturn)195c3581039SVineet Gupta SYSCALL_DEFINE0(rt_sigreturn)
196c3581039SVineet Gupta {
197c3581039SVineet Gupta struct rt_sigframe __user *sf;
198c3581039SVineet Gupta unsigned int magic;
199c3581039SVineet Gupta struct pt_regs *regs = current_pt_regs();
200c3581039SVineet Gupta
201c3581039SVineet Gupta /* Always make any pending restarted system calls return -EINTR */
202f56141e3SAndy Lutomirski current->restart_block.fn = do_no_restart_syscall;
203c3581039SVineet Gupta
204c3581039SVineet Gupta /* Since we stacked the signal on a word boundary,
205c3581039SVineet Gupta * then 'sp' should be word aligned here. If it's
206c3581039SVineet Gupta * not, then the user is trying to mess with us.
207c3581039SVineet Gupta */
208c3581039SVineet Gupta if (regs->sp & 3)
209c3581039SVineet Gupta goto badframe;
210c3581039SVineet Gupta
211c3581039SVineet Gupta sf = (struct rt_sigframe __force __user *)(regs->sp);
212c3581039SVineet Gupta
21396d4f267SLinus Torvalds if (!access_ok(sf, sizeof(*sf)))
214c3581039SVineet Gupta goto badframe;
215c3581039SVineet Gupta
21610469350SChristian Ruppert if (__get_user(magic, &sf->sigret_magic))
217c3581039SVineet Gupta goto badframe;
218c3581039SVineet Gupta
219c3581039SVineet Gupta if (unlikely(is_do_ss_needed(magic)))
220c3581039SVineet Gupta if (restore_altstack(&sf->uc.uc_stack))
221c3581039SVineet Gupta goto badframe;
222c3581039SVineet Gupta
22310469350SChristian Ruppert if (restore_usr_regs(regs, sf))
22410469350SChristian Ruppert goto badframe;
22510469350SChristian Ruppert
22655bb9480SVineet Gupta /* Don't restart from sigreturn */
22755bb9480SVineet Gupta syscall_wont_restart(regs);
22855bb9480SVineet Gupta
229e4140819SVineet Gupta /*
230e4140819SVineet Gupta * Ensure that sigreturn always returns to user mode (in case the
231e4140819SVineet Gupta * regs saved on user stack got fudged between save and sigreturn)
232e4140819SVineet Gupta * Otherwise it is easy to panic the kernel with a custom
233e4140819SVineet Gupta * signal handler and/or restorer which clobberes the status32/ret
234e4140819SVineet Gupta * to return to a bogus location in kernel mode.
235e4140819SVineet Gupta */
236e4140819SVineet Gupta regs->status32 |= STATUS_U_MASK;
237e4140819SVineet Gupta
238c3581039SVineet Gupta return regs->r0;
239c3581039SVineet Gupta
240c3581039SVineet Gupta badframe:
2413cf5d076SEric W. Biederman force_sig(SIGSEGV);
242c3581039SVineet Gupta return 0;
243c3581039SVineet Gupta }
244c3581039SVineet Gupta
245c3581039SVineet Gupta /*
246c3581039SVineet Gupta * Determine which stack to use..
247c3581039SVineet Gupta */
get_sigframe(struct ksignal * ksig,struct pt_regs * regs,unsigned long framesize)2485290dd79SRichard Weinberger static inline void __user *get_sigframe(struct ksignal *ksig,
249c3581039SVineet Gupta struct pt_regs *regs,
250c3581039SVineet Gupta unsigned long framesize)
251c3581039SVineet Gupta {
2525290dd79SRichard Weinberger unsigned long sp = sigsp(regs->sp, ksig);
253c3581039SVineet Gupta void __user *frame;
254c3581039SVineet Gupta
255c3581039SVineet Gupta /* No matter what happens, 'sp' must be word
256c3581039SVineet Gupta * aligned otherwise nasty things could happen
257c3581039SVineet Gupta */
258c3581039SVineet Gupta
259c3581039SVineet Gupta /* ATPCS B01 mandates 8-byte alignment */
260c3581039SVineet Gupta frame = (void __user *)((sp - framesize) & ~7);
261c3581039SVineet Gupta
262c3581039SVineet Gupta /* Check that we can actually write to the signal frame */
26396d4f267SLinus Torvalds if (!access_ok(frame, framesize))
264c3581039SVineet Gupta frame = NULL;
265c3581039SVineet Gupta
266c3581039SVineet Gupta return frame;
267c3581039SVineet Gupta }
268c3581039SVineet Gupta
269c3581039SVineet Gupta static int
setup_rt_frame(struct ksignal * ksig,sigset_t * set,struct pt_regs * regs)270f6dd2a3fSRichard Weinberger setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
271c3581039SVineet Gupta {
272c3581039SVineet Gupta struct rt_sigframe __user *sf;
273c3581039SVineet Gupta unsigned int magic = 0;
274c3581039SVineet Gupta int err = 0;
275c3581039SVineet Gupta
2765290dd79SRichard Weinberger sf = get_sigframe(ksig, regs, sizeof(struct rt_sigframe));
277c3581039SVineet Gupta if (!sf)
278c3581039SVineet Gupta return 1;
279c3581039SVineet Gupta
280c3581039SVineet Gupta /*
28110469350SChristian Ruppert * w/o SA_SIGINFO, struct ucontext is partially populated (only
28210469350SChristian Ruppert * uc_mcontext/uc_sigmask) for kernel's normal user state preservation
28310469350SChristian Ruppert * during signal handler execution. This works for SA_SIGINFO as well
28410469350SChristian Ruppert * although the semantics are now overloaded (the same reg state can be
28510469350SChristian Ruppert * inspected by userland: but are they allowed to fiddle with it ?
28610469350SChristian Ruppert */
28710469350SChristian Ruppert err |= stash_usr_regs(sf, regs, set);
28810469350SChristian Ruppert
28910469350SChristian Ruppert /*
290c3581039SVineet Gupta * SA_SIGINFO requires 3 args to signal handler:
291c3581039SVineet Gupta * #1: sig-no (common to any handler)
292c3581039SVineet Gupta * #2: struct siginfo
293c3581039SVineet Gupta * #3: struct ucontext (completely populated)
294c3581039SVineet Gupta */
295f6dd2a3fSRichard Weinberger if (unlikely(ksig->ka.sa.sa_flags & SA_SIGINFO)) {
296f6dd2a3fSRichard Weinberger err |= copy_siginfo_to_user(&sf->info, &ksig->info);
297c3581039SVineet Gupta err |= __put_user(0, &sf->uc.uc_flags);
298c3581039SVineet Gupta err |= __put_user(NULL, &sf->uc.uc_link);
299c3581039SVineet Gupta err |= __save_altstack(&sf->uc.uc_stack, regs->sp);
300c3581039SVineet Gupta
301c3581039SVineet Gupta /* setup args 2 and 3 for user mode handler */
302c3581039SVineet Gupta regs->r1 = (unsigned long)&sf->info;
303c3581039SVineet Gupta regs->r2 = (unsigned long)&sf->uc;
304c3581039SVineet Gupta
305c3581039SVineet Gupta /*
306f79f7a2dSBhaskar Chowdhury * small optim to avoid unconditionally calling do_sigaltstack
307c3581039SVineet Gupta * in sigreturn path, now that we only have rt_sigreturn
308c3581039SVineet Gupta */
309c3581039SVineet Gupta magic = MAGIC_SIGALTSTK;
310c3581039SVineet Gupta }
311c3581039SVineet Gupta
312c3581039SVineet Gupta err |= __put_user(magic, &sf->sigret_magic);
313c3581039SVineet Gupta if (err)
314c3581039SVineet Gupta return err;
315c3581039SVineet Gupta
316c3581039SVineet Gupta /* #1 arg to the user Signal handler */
317e6de3ca9SRichard Weinberger regs->r0 = ksig->sig;
318c3581039SVineet Gupta
319c3581039SVineet Gupta /* setup PC of user space signal handler */
320f6dd2a3fSRichard Weinberger regs->ret = (unsigned long)ksig->ka.sa.sa_handler;
321c3581039SVineet Gupta
322c3581039SVineet Gupta /*
323ecaa054fSJulia Lawall * handler returns using sigreturn stub provided already by userspace
324e4140819SVineet Gupta * If not, nuke the process right away
325c3581039SVineet Gupta */
326e4140819SVineet Gupta if(!(ksig->ka.sa.sa_flags & SA_RESTORER))
327e4140819SVineet Gupta return 1;
328e4140819SVineet Gupta
329f6dd2a3fSRichard Weinberger regs->blink = (unsigned long)ksig->ka.sa.sa_restorer;
330c3581039SVineet Gupta
331c3581039SVineet Gupta /* User Stack for signal handler will be above the frame just carved */
332c3581039SVineet Gupta regs->sp = (unsigned long)sf;
333c3581039SVineet Gupta
334c3581039SVineet Gupta /*
335c3581039SVineet Gupta * Bug 94183, Clear the DE bit, so that when signal handler
336c3581039SVineet Gupta * starts to run, it doesn't use BTA
337c3581039SVineet Gupta */
338c3581039SVineet Gupta regs->status32 &= ~STATUS_DE_MASK;
339c3581039SVineet Gupta regs->status32 |= STATUS_L_MASK;
340c3581039SVineet Gupta
341c3581039SVineet Gupta return err;
342c3581039SVineet Gupta }
343c3581039SVineet Gupta
arc_restart_syscall(struct k_sigaction * ka,struct pt_regs * regs)344c3581039SVineet Gupta static void arc_restart_syscall(struct k_sigaction *ka, struct pt_regs *regs)
345c3581039SVineet Gupta {
346c3581039SVineet Gupta switch (regs->r0) {
347c3581039SVineet Gupta case -ERESTART_RESTARTBLOCK:
348c3581039SVineet Gupta case -ERESTARTNOHAND:
349c3581039SVineet Gupta /*
350c3581039SVineet Gupta * ERESTARTNOHAND means that the syscall should
351c3581039SVineet Gupta * only be restarted if there was no handler for
352c3581039SVineet Gupta * the signal, and since we only get here if there
353c3581039SVineet Gupta * is a handler, we don't restart
354c3581039SVineet Gupta */
355c3581039SVineet Gupta regs->r0 = -EINTR; /* ERESTART_xxx is internal */
356c3581039SVineet Gupta break;
357c3581039SVineet Gupta
358c3581039SVineet Gupta case -ERESTARTSYS:
359c3581039SVineet Gupta /*
360c3581039SVineet Gupta * ERESTARTSYS means to restart the syscall if
361c3581039SVineet Gupta * there is no handler or the handler was
362c3581039SVineet Gupta * registered with SA_RESTART
363c3581039SVineet Gupta */
364c3581039SVineet Gupta if (!(ka->sa.sa_flags & SA_RESTART)) {
365c3581039SVineet Gupta regs->r0 = -EINTR;
366c3581039SVineet Gupta break;
367c3581039SVineet Gupta }
368df561f66SGustavo A. R. Silva fallthrough;
369c3581039SVineet Gupta
370c3581039SVineet Gupta case -ERESTARTNOINTR:
371c3581039SVineet Gupta /*
372c3581039SVineet Gupta * ERESTARTNOINTR means that the syscall should
373c3581039SVineet Gupta * be called again after the signal handler returns.
374c3581039SVineet Gupta * Setup reg state just as it was before doing the trap
375c3581039SVineet Gupta * r0 has been clobbered with sys call ret code thus it
376c3581039SVineet Gupta * needs to be reloaded with orig first arg to syscall
377c3581039SVineet Gupta * in orig_r0. Rest of relevant reg-file:
378c3581039SVineet Gupta * r8 (syscall num) and (r1 - r7) will be reset to
379c3581039SVineet Gupta * their orig user space value when we ret from kernel
380c3581039SVineet Gupta */
381c3581039SVineet Gupta regs->r0 = regs->orig_r0;
3821f6ccfffSVineet Gupta regs->ret -= is_isa_arcv2() ? 2 : 4;
383c3581039SVineet Gupta break;
384c3581039SVineet Gupta }
385c3581039SVineet Gupta }
386c3581039SVineet Gupta
387c3581039SVineet Gupta /*
388c3581039SVineet Gupta * OK, we're invoking a handler
389c3581039SVineet Gupta */
390c3581039SVineet Gupta static void
handle_signal(struct ksignal * ksig,struct pt_regs * regs)391f6dd2a3fSRichard Weinberger handle_signal(struct ksignal *ksig, struct pt_regs *regs)
392c3581039SVineet Gupta {
393c3581039SVineet Gupta sigset_t *oldset = sigmask_to_save();
394e4140819SVineet Gupta int failed;
395c3581039SVineet Gupta
396c3581039SVineet Gupta /* Set up the stack frame */
397e4140819SVineet Gupta failed = setup_rt_frame(ksig, oldset, regs);
398c3581039SVineet Gupta
399e4140819SVineet Gupta signal_setup_done(failed, ksig, 0);
400c3581039SVineet Gupta }
401c3581039SVineet Gupta
do_signal(struct pt_regs * regs)402c3581039SVineet Gupta void do_signal(struct pt_regs *regs)
403c3581039SVineet Gupta {
404f6dd2a3fSRichard Weinberger struct ksignal ksig;
405c3581039SVineet Gupta int restart_scall;
406c3581039SVineet Gupta
40755bb9480SVineet Gupta restart_scall = in_syscall(regs) && syscall_restartable(regs);
408c3581039SVineet Gupta
40953855e12SJens Axboe if (test_thread_flag(TIF_SIGPENDING) && get_signal(&ksig)) {
41055bb9480SVineet Gupta if (restart_scall) {
411f6dd2a3fSRichard Weinberger arc_restart_syscall(&ksig.ka, regs);
41255bb9480SVineet Gupta syscall_wont_restart(regs); /* No more restarts */
41355bb9480SVineet Gupta }
414f6dd2a3fSRichard Weinberger handle_signal(&ksig, regs);
415c3581039SVineet Gupta return;
416c3581039SVineet Gupta }
417c3581039SVineet Gupta
418c3581039SVineet Gupta if (restart_scall) {
419c3581039SVineet Gupta /* No handler for syscall: restart it */
420c3581039SVineet Gupta if (regs->r0 == -ERESTARTNOHAND ||
421c3581039SVineet Gupta regs->r0 == -ERESTARTSYS || regs->r0 == -ERESTARTNOINTR) {
422c3581039SVineet Gupta regs->r0 = regs->orig_r0;
4231f6ccfffSVineet Gupta regs->ret -= is_isa_arcv2() ? 2 : 4;
424c3581039SVineet Gupta } else if (regs->r0 == -ERESTART_RESTARTBLOCK) {
425c3581039SVineet Gupta regs->r8 = __NR_restart_syscall;
4261f6ccfffSVineet Gupta regs->ret -= is_isa_arcv2() ? 2 : 4;
427c3581039SVineet Gupta }
42855bb9480SVineet Gupta syscall_wont_restart(regs); /* No more restarts */
429c3581039SVineet Gupta }
430c3581039SVineet Gupta
431c3581039SVineet Gupta /* If there's no signal to deliver, restore the saved sigmask back */
432c3581039SVineet Gupta restore_saved_sigmask();
433c3581039SVineet Gupta }
434c3581039SVineet Gupta
do_notify_resume(struct pt_regs * regs)435c3581039SVineet Gupta void do_notify_resume(struct pt_regs *regs)
436c3581039SVineet Gupta {
437c3581039SVineet Gupta /*
438f79f7a2dSBhaskar Chowdhury * ASM glue guarantees that this is only called when returning to
439c3581039SVineet Gupta * user mode
440c3581039SVineet Gupta */
4413c532798SJens Axboe if (test_thread_flag(TIF_NOTIFY_RESUME))
44203248addSEric W. Biederman resume_user_mode_work(regs);
443c3581039SVineet Gupta }
444