~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/parisc/kernel/signal.c

Version: ~ [ linux-5.1-rc5 ] ~ [ linux-5.0.7 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.34 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.111 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.168 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.178 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.138 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.65 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.39.4 ] ~ [ linux-2.6.38.8 ] ~ [ linux-2.6.37.6 ] ~ [ linux-2.6.36.4 ] ~ [ linux-2.6.35.14 ] ~ [ linux-2.6.34.15 ] ~ [ linux-2.6.33.20 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3  *  linux/arch/parisc/kernel/signal.c: Architecture-specific signal
  4  *  handling support.
  5  *
  6  *  Copyright (C) 2000 David Huggins-Daines <dhd@debian.org>
  7  *  Copyright (C) 2000 Linuxcare, Inc.
  8  *
  9  *  Based on the ia64, i386, and alpha versions.
 10  *
 11  *  Like the IA-64, we are a recent enough port (we are *starting*
 12  *  with glibc2.2) that we do not need to support the old non-realtime
 13  *  Linux signals.  Therefore we don't.
 14  */
 15 
 16 #include <linux/sched.h>
 17 #include <linux/sched/debug.h>
 18 #include <linux/mm.h>
 19 #include <linux/smp.h>
 20 #include <linux/kernel.h>
 21 #include <linux/signal.h>
 22 #include <linux/errno.h>
 23 #include <linux/wait.h>
 24 #include <linux/ptrace.h>
 25 #include <linux/tracehook.h>
 26 #include <linux/unistd.h>
 27 #include <linux/stddef.h>
 28 #include <linux/compat.h>
 29 #include <linux/elf.h>
 30 #include <asm/ucontext.h>
 31 #include <asm/rt_sigframe.h>
 32 #include <linux/uaccess.h>
 33 #include <asm/pgalloc.h>
 34 #include <asm/cacheflush.h>
 35 #include <asm/asm-offsets.h>
 36 
 37 #ifdef CONFIG_COMPAT
 38 #include "signal32.h"
 39 #endif
 40 
 41 #define DEBUG_SIG 0 
 42 #define DEBUG_SIG_LEVEL 2
 43 
 44 #if DEBUG_SIG
 45 #define DBG(LEVEL, ...) \
 46         ((DEBUG_SIG_LEVEL >= LEVEL) \
 47         ? printk(__VA_ARGS__) : (void) 0)
 48 #else
 49 #define DBG(LEVEL, ...)
 50 #endif
 51         
 52 /* gcc will complain if a pointer is cast to an integer of different
 53  * size.  If you really need to do this (and we do for an ELF32 user
 54  * application in an ELF64 kernel) then you have to do a cast to an
 55  * integer of the same size first.  The A() macro accomplishes
 56  * this. */
 57 #define A(__x)  ((unsigned long)(__x))
 58 
 59 /*
 60  * Do a signal return - restore sigcontext.
 61  */
 62 
 63 /* Trampoline for calling rt_sigreturn() */
 64 #define INSN_LDI_R25_0   0x34190000 /* ldi  0,%r25 (in_syscall=0) */
 65 #define INSN_LDI_R25_1   0x34190002 /* ldi  1,%r25 (in_syscall=1) */
 66 #define INSN_LDI_R20     0x3414015a /* ldi  __NR_rt_sigreturn,%r20 */
 67 #define INSN_BLE_SR2_R0  0xe4008200 /* be,l 0x100(%sr2,%r0),%sr0,%r31 */
 68 #define INSN_NOP         0x08000240 /* nop */
 69 /* For debugging */
 70 #define INSN_DIE_HORRIBLY 0x68000ccc /* stw %r0,0x666(%sr0,%r0) */
 71 
 72 static long
 73 restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
 74 {
 75         long err = 0;
 76 
 77         err |= __copy_from_user(regs->gr, sc->sc_gr, sizeof(regs->gr));
 78         err |= __copy_from_user(regs->fr, sc->sc_fr, sizeof(regs->fr));
 79         err |= __copy_from_user(regs->iaoq, sc->sc_iaoq, sizeof(regs->iaoq));
 80         err |= __copy_from_user(regs->iasq, sc->sc_iasq, sizeof(regs->iasq));
 81         err |= __get_user(regs->sar, &sc->sc_sar);
 82         DBG(2,"restore_sigcontext: iaoq is %#lx / %#lx\n",
 83                         regs->iaoq[0],regs->iaoq[1]);
 84         DBG(2,"restore_sigcontext: r28 is %ld\n", regs->gr[28]);
 85         return err;
 86 }
 87 
 88 void
 89 sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
 90 {
 91         struct rt_sigframe __user *frame;
 92         sigset_t set;
 93         unsigned long usp = (regs->gr[30] & ~(0x01UL));
 94         unsigned long sigframe_size = PARISC_RT_SIGFRAME_SIZE;
 95 #ifdef CONFIG_64BIT
 96         struct compat_rt_sigframe __user * compat_frame;
 97         
 98         if (is_compat_task())
 99                 sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
100 #endif
101 
102         current->restart_block.fn = do_no_restart_syscall;
103 
104         /* Unwind the user stack to get the rt_sigframe structure. */
105         frame = (struct rt_sigframe __user *)
106                 (usp - sigframe_size);
107         DBG(2,"sys_rt_sigreturn: frame is %p\n", frame);
108 
109         regs->orig_r28 = 1; /* no restarts for sigreturn */
110 
111 #ifdef CONFIG_64BIT
112         compat_frame = (struct compat_rt_sigframe __user *)frame;
113         
114         if (is_compat_task()) {
115                 DBG(2,"sys_rt_sigreturn: ELF32 process.\n");
116                 if (get_compat_sigset(&set, &compat_frame->uc.uc_sigmask))
117                         goto give_sigsegv;
118         } else
119 #endif
120         {
121                 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
122                         goto give_sigsegv;
123         }
124                 
125         set_current_blocked(&set);
126 
127         /* Good thing we saved the old gr[30], eh? */
128 #ifdef CONFIG_64BIT
129         if (is_compat_task()) {
130                 DBG(1,"sys_rt_sigreturn: compat_frame->uc.uc_mcontext 0x%p\n",
131                                 &compat_frame->uc.uc_mcontext);
132 // FIXME: Load upper half from register file
133                 if (restore_sigcontext32(&compat_frame->uc.uc_mcontext, 
134                                         &compat_frame->regs, regs))
135                         goto give_sigsegv;
136                 DBG(1,"sys_rt_sigreturn: usp %#08lx stack 0x%p\n", 
137                                 usp, &compat_frame->uc.uc_stack);
138                 if (compat_restore_altstack(&compat_frame->uc.uc_stack))
139                         goto give_sigsegv;
140         } else
141 #endif
142         {
143                 DBG(1,"sys_rt_sigreturn: frame->uc.uc_mcontext 0x%p\n",
144                                 &frame->uc.uc_mcontext);
145                 if (restore_sigcontext(&frame->uc.uc_mcontext, regs))
146                         goto give_sigsegv;
147                 DBG(1,"sys_rt_sigreturn: usp %#08lx stack 0x%p\n", 
148                                 usp, &frame->uc.uc_stack);
149                 if (restore_altstack(&frame->uc.uc_stack))
150                         goto give_sigsegv;
151         }
152                 
153 
154 
155         /* If we are on the syscall path IAOQ will not be restored, and
156          * if we are on the interrupt path we must not corrupt gr31.
157          */
158         if (in_syscall)
159                 regs->gr[31] = regs->iaoq[0];
160 #if DEBUG_SIG
161         DBG(1,"sys_rt_sigreturn: returning to %#lx, DUMPING REGS:\n", regs->iaoq[0]);
162         show_regs(regs);
163 #endif
164         return;
165 
166 give_sigsegv:
167         DBG(1,"sys_rt_sigreturn: Sending SIGSEGV\n");
168         force_sig(SIGSEGV, current);
169         return;
170 }
171 
172 /*
173  * Set up a signal frame.
174  */
175 
176 static inline void __user *
177 get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
178 {
179         /*FIXME: ELF32 vs. ELF64 has different frame_size, but since we
180           don't use the parameter it doesn't matter */
181 
182         DBG(1,"get_sigframe: ka = %#lx, sp = %#lx, frame_size = %#lx\n",
183                         (unsigned long)ka, sp, frame_size);
184         
185         /* Align alternate stack and reserve 64 bytes for the signal
186            handler's frame marker.  */
187         if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
188                 sp = (current->sas_ss_sp + 0x7f) & ~0x3f; /* Stacks grow up! */
189 
190         DBG(1,"get_sigframe: Returning sp = %#lx\n", (unsigned long)sp);
191         return (void __user *) sp; /* Stacks grow up.  Fun. */
192 }
193 
194 static long
195 setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, int in_syscall)
196                  
197 {
198         unsigned long flags = 0;
199         long err = 0;
200 
201         if (on_sig_stack((unsigned long) sc))
202                 flags |= PARISC_SC_FLAG_ONSTACK;
203         if (in_syscall) {
204                 flags |= PARISC_SC_FLAG_IN_SYSCALL;
205                 /* regs->iaoq is undefined in the syscall return path */
206                 err |= __put_user(regs->gr[31], &sc->sc_iaoq[0]);
207                 err |= __put_user(regs->gr[31]+4, &sc->sc_iaoq[1]);
208                 err |= __put_user(regs->sr[3], &sc->sc_iasq[0]);
209                 err |= __put_user(regs->sr[3], &sc->sc_iasq[1]);
210                 DBG(1,"setup_sigcontext: iaoq %#lx / %#lx (in syscall)\n",
211                         regs->gr[31], regs->gr[31]+4);
212         } else {
213                 err |= __copy_to_user(sc->sc_iaoq, regs->iaoq, sizeof(regs->iaoq));
214                 err |= __copy_to_user(sc->sc_iasq, regs->iasq, sizeof(regs->iasq));
215                 DBG(1,"setup_sigcontext: iaoq %#lx / %#lx (not in syscall)\n", 
216                         regs->iaoq[0], regs->iaoq[1]);
217         }
218 
219         err |= __put_user(flags, &sc->sc_flags);
220         err |= __copy_to_user(sc->sc_gr, regs->gr, sizeof(regs->gr));
221         err |= __copy_to_user(sc->sc_fr, regs->fr, sizeof(regs->fr));
222         err |= __put_user(regs->sar, &sc->sc_sar);
223         DBG(1,"setup_sigcontext: r28 is %ld\n", regs->gr[28]);
224 
225         return err;
226 }
227 
228 static long
229 setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs,
230                int in_syscall)
231 {
232         struct rt_sigframe __user *frame;
233         unsigned long rp, usp;
234         unsigned long haddr, sigframe_size;
235         unsigned long start, end;
236         int err = 0;
237 #ifdef CONFIG_64BIT
238         struct compat_rt_sigframe __user * compat_frame;
239 #endif
240         
241         usp = (regs->gr[30] & ~(0x01UL));
242         /*FIXME: frame_size parameter is unused, remove it. */
243         frame = get_sigframe(&ksig->ka, usp, sizeof(*frame));
244 
245         DBG(1,"SETUP_RT_FRAME: START\n");
246         DBG(1,"setup_rt_frame: frame %p info %p\n", frame, ksig->info);
247 
248         
249 #ifdef CONFIG_64BIT
250 
251         compat_frame = (struct compat_rt_sigframe __user *)frame;
252         
253         if (is_compat_task()) {
254                 DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &compat_frame->info);
255                 err |= copy_siginfo_to_user32(&compat_frame->info, &ksig->info);
256                 err |= __compat_save_altstack( &compat_frame->uc.uc_stack, regs->gr[30]);
257                 DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &compat_frame->uc);
258                 DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &compat_frame->uc.uc_mcontext);
259                 err |= setup_sigcontext32(&compat_frame->uc.uc_mcontext, 
260                                         &compat_frame->regs, regs, in_syscall);
261                 err |= put_compat_sigset(&compat_frame->uc.uc_sigmask, set,
262                                          sizeof(compat_sigset_t));
263         } else
264 #endif
265         {       
266                 DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &frame->info);
267                 err |= copy_siginfo_to_user(&frame->info, &ksig->info);
268                 err |= __save_altstack(&frame->uc.uc_stack, regs->gr[30]);
269                 DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &frame->uc);
270                 DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &frame->uc.uc_mcontext);
271                 err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, in_syscall);
272                 /* FIXME: Should probably be converted as well for the compat case */
273                 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
274         }
275         
276         if (err)
277                 return -EFAULT;
278 
279         /* Set up to return from userspace.  If provided, use a stub
280            already in userspace. The first words of tramp are used to
281            save the previous sigrestartblock trampoline that might be
282            on the stack. We start the sigreturn trampoline at 
283            SIGRESTARTBLOCK_TRAMP+X. */
284         err |= __put_user(in_syscall ? INSN_LDI_R25_1 : INSN_LDI_R25_0,
285                         &frame->tramp[SIGRESTARTBLOCK_TRAMP+0]);
286         err |= __put_user(INSN_LDI_R20, 
287                         &frame->tramp[SIGRESTARTBLOCK_TRAMP+1]);
288         err |= __put_user(INSN_BLE_SR2_R0, 
289                         &frame->tramp[SIGRESTARTBLOCK_TRAMP+2]);
290         err |= __put_user(INSN_NOP, &frame->tramp[SIGRESTARTBLOCK_TRAMP+3]);
291 
292 #if DEBUG_SIG
293         /* Assert that we're flushing in the correct space... */
294         {
295                 unsigned long sid;
296                 asm ("mfsp %%sr3,%0" : "=r" (sid));
297                 DBG(1,"setup_rt_frame: Flushing 64 bytes at space %#x offset %p\n",
298                        sid, frame->tramp);
299         }
300 #endif
301 
302         start = (unsigned long) &frame->tramp[0];
303         end = (unsigned long) &frame->tramp[TRAMP_SIZE];
304         flush_user_dcache_range_asm(start, end);
305         flush_user_icache_range_asm(start, end);
306 
307         /* TRAMP Words 0-4, Length 5 = SIGRESTARTBLOCK_TRAMP
308          * TRAMP Words 5-9, Length 4 = SIGRETURN_TRAMP
309          * So the SIGRETURN_TRAMP is at the end of SIGRESTARTBLOCK_TRAMP
310          */
311         rp = (unsigned long) &frame->tramp[SIGRESTARTBLOCK_TRAMP];
312 
313         if (err)
314                 return -EFAULT;
315 
316         haddr = A(ksig->ka.sa.sa_handler);
317         /* The sa_handler may be a pointer to a function descriptor */
318 #ifdef CONFIG_64BIT
319         if (is_compat_task()) {
320 #endif
321                 if (haddr & PA_PLABEL_FDESC) {
322                         Elf32_Fdesc fdesc;
323                         Elf32_Fdesc __user *ufdesc = (Elf32_Fdesc __user *)A(haddr & ~3);
324 
325                         err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
326 
327                         if (err)
328                                 return -EFAULT;
329 
330                         haddr = fdesc.addr;
331                         regs->gr[19] = fdesc.gp;
332                 }
333 #ifdef CONFIG_64BIT
334         } else {
335                 Elf64_Fdesc fdesc;
336                 Elf64_Fdesc __user *ufdesc = (Elf64_Fdesc __user *)A(haddr & ~3);
337                 
338                 err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
339                 
340                 if (err)
341                         return -EFAULT;
342                 
343                 haddr = fdesc.addr;
344                 regs->gr[19] = fdesc.gp;
345                 DBG(1,"setup_rt_frame: 64 bit signal, exe=%#lx, r19=%#lx, in_syscall=%d\n",
346                      haddr, regs->gr[19], in_syscall);
347         }
348 #endif
349 
350         /* The syscall return path will create IAOQ values from r31.
351          */
352         sigframe_size = PARISC_RT_SIGFRAME_SIZE;
353 #ifdef CONFIG_64BIT
354         if (is_compat_task())
355                 sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
356 #endif
357         if (in_syscall) {
358                 regs->gr[31] = haddr;
359 #ifdef CONFIG_64BIT
360                 if (!test_thread_flag(TIF_32BIT))
361                         sigframe_size |= 1;
362 #endif
363         } else {
364                 unsigned long psw = USER_PSW;
365 #ifdef CONFIG_64BIT
366                 if (!test_thread_flag(TIF_32BIT))
367                         psw |= PSW_W;
368 #endif
369 
370                 /* If we are singlestepping, arrange a trap to be delivered
371                    when we return to userspace. Note the semantics -- we
372                    should trap before the first insn in the handler is
373                    executed. Ref:
374                         http://sources.redhat.com/ml/gdb/2004-11/msg00245.html
375                  */
376                 if (pa_psw(current)->r) {
377                         pa_psw(current)->r = 0;
378                         psw |= PSW_R;
379                         mtctl(-1, 0);
380                 }
381 
382                 regs->gr[0] = psw;
383                 regs->iaoq[0] = haddr | 3;
384                 regs->iaoq[1] = regs->iaoq[0] + 4;
385         }
386 
387         regs->gr[2]  = rp;                /* userland return pointer */
388         regs->gr[26] = ksig->sig;               /* signal number */
389         
390 #ifdef CONFIG_64BIT
391         if (is_compat_task()) {
392                 regs->gr[25] = A(&compat_frame->info); /* siginfo pointer */
393                 regs->gr[24] = A(&compat_frame->uc);   /* ucontext pointer */
394         } else
395 #endif
396         {               
397                 regs->gr[25] = A(&frame->info); /* siginfo pointer */
398                 regs->gr[24] = A(&frame->uc);   /* ucontext pointer */
399         }
400         
401         DBG(1,"setup_rt_frame: making sigreturn frame: %#lx + %#lx = %#lx\n",
402                regs->gr[30], sigframe_size,
403                regs->gr[30] + sigframe_size);
404         /* Raise the user stack pointer to make a proper call frame. */
405         regs->gr[30] = (A(frame) + sigframe_size);
406 
407 
408         DBG(1,"setup_rt_frame: sig deliver (%s,%d) frame=0x%p sp=%#lx iaoq=%#lx/%#lx rp=%#lx\n",
409                current->comm, current->pid, frame, regs->gr[30],
410                regs->iaoq[0], regs->iaoq[1], rp);
411 
412         return 0;
413 }
414 
415 /*
416  * OK, we're invoking a handler.
417  */     
418 
419 static void
420 handle_signal(struct ksignal *ksig, struct pt_regs *regs, int in_syscall)
421 {
422         int ret;
423         sigset_t *oldset = sigmask_to_save();
424 
425         DBG(1,"handle_signal: sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p\n",
426                ksig->sig, ksig->ka, ksig->info, oldset, regs);
427         
428         /* Set up the stack frame */
429         ret = setup_rt_frame(ksig, oldset, regs, in_syscall);
430 
431         signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP) ||
432                           test_thread_flag(TIF_BLOCKSTEP));
433 
434         DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
435                 regs->gr[28]);
436 }
437 
438 /*
439  * Check how the syscall number gets loaded into %r20 within
440  * the delay branch in userspace and adjust as needed.
441  */
442 
443 static void check_syscallno_in_delay_branch(struct pt_regs *regs)
444 {
445         u32 opcode, source_reg;
446         u32 __user *uaddr;
447         int err;
448 
449         /* Usually we don't have to restore %r20 (the system call number)
450          * because it gets loaded in the delay slot of the branch external
451          * instruction via the ldi instruction.
452          * In some cases a register-to-register copy instruction might have
453          * been used instead, in which case we need to copy the syscall
454          * number into the source register before returning to userspace.
455          */
456 
457         /* A syscall is just a branch, so all we have to do is fiddle the
458          * return pointer so that the ble instruction gets executed again.
459          */
460         regs->gr[31] -= 8; /* delayed branching */
461 
462         /* Get assembler opcode of code in delay branch */
463         uaddr = (unsigned int *) ((regs->gr[31] & ~3) + 4);
464         err = get_user(opcode, uaddr);
465         if (err)
466                 return;
467 
468         /* Check if delay branch uses "ldi int,%r20" */
469         if ((opcode & 0xffff0000) == 0x34140000)
470                 return; /* everything ok, just return */
471 
472         /* Check if delay branch uses "nop" */
473         if (opcode == INSN_NOP)
474                 return;
475 
476         /* Check if delay branch uses "copy %rX,%r20" */
477         if ((opcode & 0xffe0ffff) == 0x08000254) {
478                 source_reg = (opcode >> 16) & 31;
479                 regs->gr[source_reg] = regs->gr[20];
480                 return;
481         }
482 
483         pr_warn("syscall restart: %s (pid %d): unexpected opcode 0x%08x\n",
484                 current->comm, task_pid_nr(current), opcode);
485 }
486 
487 static inline void
488 syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
489 {
490         if (regs->orig_r28)
491                 return;
492         regs->orig_r28 = 1; /* no more restarts */
493         /* Check the return code */
494         switch (regs->gr[28]) {
495         case -ERESTART_RESTARTBLOCK:
496         case -ERESTARTNOHAND:
497                 DBG(1,"ERESTARTNOHAND: returning -EINTR\n");
498                 regs->gr[28] = -EINTR;
499                 break;
500 
501         case -ERESTARTSYS:
502                 if (!(ka->sa.sa_flags & SA_RESTART)) {
503                         DBG(1,"ERESTARTSYS: putting -EINTR\n");
504                         regs->gr[28] = -EINTR;
505                         break;
506                 }
507                 /* fallthrough */
508         case -ERESTARTNOINTR:
509                 check_syscallno_in_delay_branch(regs);
510                 break;
511         }
512 }
513 
514 static inline void
515 insert_restart_trampoline(struct pt_regs *regs)
516 {
517         if (regs->orig_r28)
518                 return;
519         regs->orig_r28 = 1; /* no more restarts */
520         switch(regs->gr[28]) {
521         case -ERESTART_RESTARTBLOCK: {
522                 /* Restart the system call - no handlers present */
523                 unsigned int *usp = (unsigned int *)regs->gr[30];
524                 unsigned long start = (unsigned long) &usp[2];
525                 unsigned long end  = (unsigned long) &usp[5];
526                 long err = 0;
527 
528                 /* Setup a trampoline to restart the syscall
529                  * with __NR_restart_syscall
530                  *
531                  *  0: <return address (orig r31)>
532                  *  4: <2nd half for 64-bit>
533                  *  8: ldw 0(%sp), %r31
534                  * 12: be 0x100(%sr2, %r0)
535                  * 16: ldi __NR_restart_syscall, %r20
536                  */
537 #ifdef CONFIG_64BIT
538                 err |= put_user(regs->gr[31] >> 32, &usp[0]);
539                 err |= put_user(regs->gr[31] & 0xffffffff, &usp[1]);
540                 err |= put_user(0x0fc010df, &usp[2]);
541 #else
542                 err |= put_user(regs->gr[31], &usp[0]);
543                 err |= put_user(0x0fc0109f, &usp[2]);
544 #endif
545                 err |= put_user(0xe0008200, &usp[3]);
546                 err |= put_user(0x34140000, &usp[4]);
547 
548                 WARN_ON(err);
549 
550                 /* flush data/instruction cache for new insns */
551                 flush_user_dcache_range_asm(start, end);
552                 flush_user_icache_range_asm(start, end);
553 
554                 regs->gr[31] = regs->gr[30] + 8;
555                 return;
556         }
557         case -ERESTARTNOHAND:
558         case -ERESTARTSYS:
559         case -ERESTARTNOINTR:
560                 check_syscallno_in_delay_branch(regs);
561                 return;
562         default:
563                 break;
564         }
565 }
566 
567 /*
568  * Note that 'init' is a special process: it doesn't get signals it doesn't
569  * want to handle. Thus you cannot kill init even with a SIGKILL even by
570  * mistake.
571  *
572  * We need to be able to restore the syscall arguments (r21-r26) to
573  * restart syscalls.  Thus, the syscall path should save them in the
574  * pt_regs structure (it's okay to do so since they are caller-save
575  * registers).  As noted below, the syscall number gets restored for
576  * us due to the magic of delayed branching.
577  */
578 asmlinkage void
579 do_signal(struct pt_regs *regs, long in_syscall)
580 {
581         struct ksignal ksig;
582 
583         DBG(1,"\ndo_signal: regs=0x%p, sr7 %#lx, in_syscall=%d\n",
584                regs, regs->sr[7], in_syscall);
585 
586         if (get_signal(&ksig)) {
587                 DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]);
588                 /* Restart a system call if necessary. */
589                 if (in_syscall)
590                         syscall_restart(regs, &ksig.ka);
591 
592                 handle_signal(&ksig, regs, in_syscall);
593                 return;
594         }
595 
596         /* Did we come from a system call? */
597         if (in_syscall)
598                 insert_restart_trampoline(regs);
599         
600         DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n", 
601                 regs->gr[28]);
602 
603         restore_saved_sigmask();
604 }
605 
606 void do_notify_resume(struct pt_regs *regs, long in_syscall)
607 {
608         if (test_thread_flag(TIF_SIGPENDING))
609                 do_signal(regs, in_syscall);
610 
611         if (test_thread_flag(TIF_NOTIFY_RESUME)) {
612                 clear_thread_flag(TIF_NOTIFY_RESUME);
613                 tracehook_notify_resume(regs);
614         }
615 }
616 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp