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

TOMOYO Linux Cross Reference
Linux/arch/mips/kernel/irixsig.c

Version: ~ [ linux-5.7-rc7 ] ~ [ linux-5.6.14 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.42 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.124 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.181 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.224 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.224 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.84 ] ~ [ 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-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 /*
  2  * irixsig.c: WHEEE, IRIX signals!  YOW, am I compatible or what?!?!
  3  *
  4  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  5  * Copyright (C) 1997 - 2000 Ralf Baechle (ralf@gnu.org)
  6  * Copyright (C) 2000 Silicon Graphics, Inc.
  7  */
  8 #include <linux/kernel.h>
  9 #include <linux/sched.h>
 10 #include <linux/mm.h>
 11 #include <linux/errno.h>
 12 #include <linux/smp.h>
 13 #include <linux/smp_lock.h>
 14 #include <linux/time.h>
 15 #include <linux/ptrace.h>
 16 
 17 #include <asm/ptrace.h>
 18 #include <asm/uaccess.h>
 19 
 20 extern asmlinkage void do_syscall_trace(void);
 21 
 22 #undef DEBUG_SIG
 23 
 24 #define _S(nr) (1<<((nr)-1))
 25 
 26 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
 27 
 28 typedef struct {
 29         unsigned long sig[4];
 30 } irix_sigset_t;
 31 
 32 struct sigctx_irix5 {
 33         u32 rmask, cp0_status;
 34         u64 pc;
 35         u64 regs[32];
 36         u64 fpregs[32];
 37         u32 usedfp, fpcsr, fpeir, sstk_flags;
 38         u64 hi, lo;
 39         u64 cp0_cause, cp0_badvaddr, _unused0;
 40         irix_sigset_t sigset;
 41         u64 weird_fpu_thing;
 42         u64 _unused1[31];
 43 };
 44 
 45 #ifdef DEBUG_SIG
 46 /* Debugging */
 47 static inline void dump_irix5_sigctx(struct sigctx_irix5 *c)
 48 {
 49         int i;
 50 
 51         printk("misc: rmask[%08lx] status[%08lx] pc[%08lx]\n",
 52                (unsigned long) c->rmask,
 53                (unsigned long) c->cp0_status,
 54                (unsigned long) c->pc);
 55         printk("regs: ");
 56         for(i = 0; i < 16; i++)
 57                 printk("[%d]<%08lx> ", i, (unsigned long) c->regs[i]);
 58         printk("\nregs: ");
 59         for(i = 16; i < 32; i++)
 60                 printk("[%d]<%08lx> ", i, (unsigned long) c->regs[i]);
 61         printk("\nfpregs: ");
 62         for(i = 0; i < 16; i++)
 63                 printk("[%d]<%08lx> ", i, (unsigned long) c->fpregs[i]);
 64         printk("\nfpregs: ");
 65         for(i = 16; i < 32; i++)
 66                 printk("[%d]<%08lx> ", i, (unsigned long) c->fpregs[i]);
 67         printk("misc: usedfp[%d] fpcsr[%08lx] fpeir[%08lx] stk_flgs[%08lx]\n",
 68                (int) c->usedfp, (unsigned long) c->fpcsr,
 69                (unsigned long) c->fpeir, (unsigned long) c->sstk_flags);
 70         printk("misc: hi[%08lx] lo[%08lx] cause[%08lx] badvaddr[%08lx]\n",
 71                (unsigned long) c->hi, (unsigned long) c->lo,
 72                (unsigned long) c->cp0_cause, (unsigned long) c->cp0_badvaddr);
 73         printk("misc: sigset<0>[%08lx] sigset<1>[%08lx] sigset<2>[%08lx] "
 74                "sigset<3>[%08lx]\n", (unsigned long) c->sigset.sig[0],
 75                (unsigned long) c->sigset.sig[1],
 76                (unsigned long) c->sigset.sig[2],
 77                (unsigned long) c->sigset.sig[3]);
 78 }
 79 #endif
 80 
 81 static void setup_irix_frame(struct k_sigaction *ka, struct pt_regs *regs,
 82                              int signr, sigset_t *oldmask)
 83 {
 84         unsigned long sp;
 85         struct sigctx_irix5 *ctx;
 86         int i;
 87 
 88         sp = regs->regs[29];
 89         sp -= sizeof(struct sigctx_irix5);
 90         sp &= ~(0xf);
 91         ctx = (struct sigctx_irix5 *) sp;
 92         if (!access_ok(VERIFY_WRITE, ctx, sizeof(*ctx)))
 93                 goto segv_and_exit;
 94 
 95         __put_user(0, &ctx->weird_fpu_thing);
 96         __put_user(~(0x00000001), &ctx->rmask);
 97         __put_user(0, &ctx->regs[0]);
 98         for(i = 1; i < 32; i++)
 99                 __put_user((u64) regs->regs[i], &ctx->regs[i]);
100 
101         __put_user((u64) regs->hi, &ctx->hi);
102         __put_user((u64) regs->lo, &ctx->lo);
103         __put_user((u64) regs->cp0_epc, &ctx->pc);
104         __put_user(current->used_math, &ctx->usedfp);
105         __put_user((u64) regs->cp0_cause, &ctx->cp0_cause);
106         __put_user((u64) regs->cp0_badvaddr, &ctx->cp0_badvaddr);
107 
108         __put_user(0, &ctx->sstk_flags); /* XXX sigstack unimp... todo... */
109 
110         __copy_to_user(&ctx->sigset, oldmask, sizeof(irix_sigset_t));
111 
112 #ifdef DEBUG_SIG
113         dump_irix5_sigctx(ctx);
114 #endif
115 
116         regs->regs[4] = (unsigned long) signr;
117         regs->regs[5] = 0; /* XXX sigcode XXX */
118         regs->regs[6] = regs->regs[29] = sp;
119         regs->regs[7] = (unsigned long) ka->sa.sa_handler;
120         regs->regs[25] = regs->cp0_epc = (unsigned long) ka->sa_restorer;
121 
122         return;
123 
124 segv_and_exit:
125         if (signr == SIGSEGV)
126                 ka->sa.sa_handler = SIG_DFL;
127         force_sig(SIGSEGV, current);
128 }
129 
130 static void inline
131 setup_irix_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
132                int signr, sigset_t *oldmask, siginfo_t *info)
133 {
134         printk("Aiee: setup_tr_frame wants to be written");
135         do_exit(SIGSEGV);
136 }
137 
138 static inline void handle_signal(unsigned long sig, siginfo_t *info,
139         sigset_t *oldset, struct pt_regs * regs)
140 {
141         struct k_sigaction *ka = &current->sighand->action[sig-1];
142 
143         switch(regs->regs[0]) {
144         case ERESTARTNOHAND:
145                 regs->regs[2] = EINTR;
146                 break;
147         case ERESTARTSYS:
148                 if(!(ka->sa.sa_flags & SA_RESTART)) {
149                         regs->regs[2] = EINTR;
150                         break;
151                 }
152         /* fallthrough */
153         case ERESTARTNOINTR:            /* Userland will reload $v0.  */
154                 regs->cp0_epc -= 8;
155         }
156 
157         regs->regs[0] = 0;              /* Don't deal with this again.  */
158 
159         if (ka->sa.sa_flags & SA_SIGINFO)
160                 setup_irix_rt_frame(ka, regs, sig, oldset, info);
161         else
162                 setup_irix_frame(ka, regs, sig, oldset);
163 
164         if (ka->sa.sa_flags & SA_ONESHOT)
165                 ka->sa.sa_handler = SIG_DFL;
166         if (!(ka->sa.sa_flags & SA_NODEFER)) {
167                 spin_lock_irq(&current->sighand->siglock);
168                 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
169                 sigaddset(&current->blocked,sig);
170                 recalc_sigpending();
171                 spin_unlock_irq(&current->sighand->siglock);
172         }
173 }
174 
175 asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs)
176 {
177         siginfo_t info;
178         int signr;
179 
180         if (!oldset)
181                 oldset = &current->blocked;
182 
183         signr = get_signal_to_deliver(&info, regs, NULL);
184         if (signr > 0) {
185                 handle_signal(signr, &info, oldset, regs);
186                 return 1;
187         }
188 
189         /*
190          * Who's code doesn't conform to the restartable syscall convention
191          * dies here!!!  The li instruction, a single machine instruction,
192          * must directly be followed by the syscall instruction.
193          */
194         if (regs->regs[0]) {
195                 if (regs->regs[2] == ERESTARTNOHAND ||
196                     regs->regs[2] == ERESTARTSYS ||
197                     regs->regs[2] == ERESTARTNOINTR) {
198                         regs->cp0_epc -= 8;
199                 }
200         }
201         return 0;
202 }
203 
204 asmlinkage void
205 irix_sigreturn(struct pt_regs *regs)
206 {
207         struct sigctx_irix5 *context, *magic;
208         unsigned long umask, mask;
209         u64 *fregs;
210         int sig, i, base = 0;
211         sigset_t blocked;
212 
213         if(regs->regs[2] == 1000)
214                 base = 1;
215 
216         context = (struct sigctx_irix5 *) regs->regs[base + 4];
217         magic = (struct sigctx_irix5 *) regs->regs[base + 5];
218         sig = (int) regs->regs[base + 6];
219 #ifdef DEBUG_SIG
220         printk("[%s:%d] IRIX sigreturn(scp[%p],ucp[%p],sig[%d])\n",
221                current->comm, current->pid, context, magic, sig);
222 #endif
223         if (!context)
224                 context = magic;
225         if (!access_ok(VERIFY_READ, context, sizeof(struct sigctx_irix5)))
226                 goto badframe;
227 
228 #ifdef DEBUG_SIG
229         dump_irix5_sigctx(context);
230 #endif
231 
232         __get_user(regs->cp0_epc, &context->pc);
233         umask = context->rmask; mask = 2;
234         for (i = 1; i < 32; i++, mask <<= 1) {
235                 if(umask & mask)
236                         __get_user(regs->regs[i], &context->regs[i]);
237         }
238         __get_user(regs->hi, &context->hi);
239         __get_user(regs->lo, &context->lo);
240 
241         if ((umask & 1) && context->usedfp) {
242                 fregs = (u64 *) &current->thread.fpu;
243                 for(i = 0; i < 32; i++)
244                         fregs[i] = (u64) context->fpregs[i];
245                 __get_user(current->thread.fpu.hard.fcr31, &context->fpcsr);
246         }
247 
248         /* XXX do sigstack crapola here... XXX */
249 
250         if (__copy_from_user(&blocked, &context->sigset, sizeof(blocked)))
251                 goto badframe;
252 
253         sigdelsetmask(&blocked, ~_BLOCKABLE);
254         spin_lock_irq(&current->sighand->siglock);
255         current->blocked = blocked;
256         recalc_sigpending();
257         spin_unlock_irq(&current->sighand->siglock);
258 
259         /*
260          * Don't let your children do this ...
261          */
262         if (current_thread_info()->flags & TIF_SYSCALL_TRACE)
263                 do_syscall_trace();
264         __asm__ __volatile__(
265                 "move\t$29,%0\n\t"
266                 "j\tsyscall_exit"
267                 :/* no outputs */
268                 :"r" (&regs));
269                 /* Unreached */
270 
271 badframe:
272         force_sig(SIGSEGV, current);
273 }
274 
275 struct sigact_irix5 {
276         int flags;
277         void (*handler)(int);
278         u32 sigset[4];
279         int _unused0[2];
280 };
281 
282 #ifdef DEBUG_SIG
283 static inline void dump_sigact_irix5(struct sigact_irix5 *p)
284 {
285         printk("<f[%d] hndlr[%08lx] msk[%08lx]>", p->flags,
286                (unsigned long) p->handler,
287                (unsigned long) p->sigset[0]);
288 }
289 #endif
290 
291 asmlinkage int
292 irix_sigaction(int sig, const struct sigaction *act,
293               struct sigaction *oact, void *trampoline)
294 {
295         struct k_sigaction new_ka, old_ka;
296         int ret;
297 
298 #ifdef DEBUG_SIG
299         printk(" (%d,%s,%s,%08lx) ", sig, (!new ? "" : "NEW"),
300                (!old ? "" : "OLD"), trampoline);
301         if(new) {
302                 dump_sigact_irix5(new); printk(" ");
303         }
304 #endif
305         if (act) {
306                 sigset_t mask;
307                 if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
308                     __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
309                     __get_user(new_ka.sa.sa_flags, &act->sa_flags))
310                         return -EFAULT;
311 
312                 __copy_from_user(&mask, &act->sa_mask, sizeof(sigset_t));
313 
314                 /*
315                  * Hmmm... methinks IRIX libc always passes a valid trampoline
316                  * value for all invocations of sigaction.  Will have to
317                  * investigate.  POSIX POSIX, die die die...
318                  */
319                 new_ka.sa_restorer = trampoline;
320         }
321 
322 /* XXX Implement SIG_SETMASK32 for IRIX compatibility */
323         ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
324 
325         if (!ret && oact) {
326                 if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
327                     __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
328                     __put_user(old_ka.sa.sa_flags, &oact->sa_flags))
329                         return -EFAULT;
330                 __copy_to_user(&old_ka.sa.sa_mask, &oact->sa_mask,
331                                sizeof(sigset_t));
332         }
333 
334         return ret;
335 }
336 
337 asmlinkage int irix_sigpending(irix_sigset_t *set)
338 {
339         return do_sigpending(set, sizeof(*set));
340 }
341 
342 asmlinkage int irix_sigprocmask(int how, irix_sigset_t *new, irix_sigset_t *old)
343 {
344         sigset_t oldbits, newbits;
345         int error;
346 
347         if (new) {
348                 error = verify_area(VERIFY_READ, new, sizeof(*new));
349                 if (error)
350                         return error;
351                 __copy_from_user(&newbits, new, sizeof(unsigned long)*4);
352                 sigdelsetmask(&newbits, ~_BLOCKABLE);
353 
354                 spin_lock_irq(&current->sighand->siglock);
355                 oldbits = current->blocked;
356 
357                 switch(how) {
358                 case 1:
359                         sigorsets(&newbits, &oldbits, &newbits);
360                         break;
361 
362                 case 2:
363                         sigandsets(&newbits, &oldbits, &newbits);
364                         break;
365 
366                 case 3:
367                         break;
368 
369                 case 256:
370                         siginitset(&newbits, newbits.sig[0]);
371                         break;
372 
373                 default:
374                         return -EINVAL;
375                 }
376                 recalc_sigpending();
377                 spin_unlock_irq(&current->sighand->siglock);
378         }
379         if(old) {
380                 error = verify_area(VERIFY_WRITE, old, sizeof(*old));
381                 if(error)
382                         return error;
383                 __copy_to_user(old, &current->blocked, sizeof(unsigned long)*4);
384         }
385 
386         return 0;
387 }
388 
389 asmlinkage int irix_sigsuspend(struct pt_regs *regs)
390 {
391         sigset_t *uset, saveset, newset;
392 
393         uset = (sigset_t *) regs->regs[4];
394         if (copy_from_user(&newset, uset, sizeof(sigset_t)))
395                 return -EFAULT;
396         sigdelsetmask(&newset, ~_BLOCKABLE);
397 
398         spin_lock_irq(&current->sighand->siglock);
399         saveset = current->blocked;
400         current->blocked = newset;
401         recalc_sigpending();
402         spin_unlock_irq(&current->sighand->siglock);
403 
404         regs->regs[2] = -EINTR;
405         while (1) {
406                 current->state = TASK_INTERRUPTIBLE;
407                 schedule();
408                 if (do_irix_signal(&saveset, regs))
409                         return -EINTR;
410         }
411 }
412 
413 /* hate hate hate... */
414 struct irix5_siginfo {
415         int sig, code, error;
416         union {
417                 char unused[128 - (3 * 4)]; /* Safety net. */
418                 struct {
419                         int pid;
420                         union {
421                                 int uid;
422                                 struct {
423                                         int utime, status, stime;
424                                 } child;
425                         } procdata;
426                 } procinfo;
427 
428                 unsigned long fault_addr;
429 
430                 struct {
431                         int fd;
432                         long band;
433                 } fileinfo;
434 
435                 unsigned long sigval;
436         } stuff;
437 };
438 
439 static inline unsigned long timespectojiffies(struct timespec *value)
440 {
441         unsigned long sec = (unsigned) value->tv_sec;
442         long nsec = value->tv_nsec;
443 
444         if (sec > (LONG_MAX / HZ))
445                 return LONG_MAX;
446         nsec += 1000000000L / HZ - 1;
447         nsec /= 1000000000L / HZ;
448         return HZ * sec + nsec;
449 }
450 
451 asmlinkage int irix_sigpoll_sys(unsigned long *set, struct irix5_siginfo *info,
452                                 struct timespec *tp)
453 {
454         long expire = MAX_SCHEDULE_TIMEOUT;
455         sigset_t kset;
456         int i, sig, error, timeo = 0;
457 
458 #ifdef DEBUG_SIG
459         printk("[%s:%d] irix_sigpoll_sys(%p,%p,%p)\n",
460                current->comm, current->pid, set, info, tp);
461 #endif
462 
463         /* Must always specify the signal set. */
464         if(!set)
465                 return -EINVAL;
466 
467         error = verify_area(VERIFY_READ, set, sizeof(kset));
468         if (error)
469                 goto out;
470 
471         __copy_from_user(&kset, set, sizeof(set));
472         if (error)
473                 goto out;
474 
475         if (info && clear_user(info, sizeof(*info))) {
476                 error = -EFAULT;
477                 goto out;
478         }
479 
480         if(tp) {
481                 error = verify_area(VERIFY_READ, tp, sizeof(*tp));
482                 if(error)
483                         return error;
484                 if(!tp->tv_sec && !tp->tv_nsec) {
485                         error = -EINVAL;
486                         goto out;
487                 }
488                 expire = timespectojiffies(tp)+(tp->tv_sec||tp->tv_nsec);
489         }
490 
491         while(1) {
492                 long tmp = 0;
493 
494                 current->state = TASK_INTERRUPTIBLE;
495                 expire = schedule_timeout(expire);
496 
497                 for (i=0; i<=4; i++)
498                         tmp |= (current->pending.signal.sig[i] & kset.sig[i]);
499 
500                 if (tmp)
501                         break;
502                 if (!expire) {
503                         timeo = 1;
504                         break;
505                 }
506                 if (signal_pending(current))
507                         return -EINTR;
508         }
509         if (timeo)
510                 return -EAGAIN;
511 
512         for(sig = 1; i <= 65 /* IRIX_NSIG */; sig++) {
513                 if (sigismember (&kset, sig))
514                         continue;
515                 if (sigismember (&current->pending.signal, sig)) {
516                         /* XXX need more than this... */
517                         if (info)
518                                 info->sig = sig;
519                         error = 0;
520                         goto out;
521                 }
522         }
523 
524         /* Should not get here, but do something sane if we do. */
525         error = -EINTR;
526 
527 out:
528         return error;
529 }
530 
531 /* This is here because of irix5_siginfo definition. */
532 #define P_PID    0
533 #define P_PGID   2
534 #define P_ALL    7
535 
536 extern int getrusage(struct task_struct *, int, struct rusage *);
537 
538 #define W_EXITED     1
539 #define W_TRAPPED    2
540 #define W_STOPPED    4
541 #define W_CONT       8
542 #define W_NOHANG    64
543 
544 #define W_MASK      (W_EXITED | W_TRAPPED | W_STOPPED | W_CONT | W_NOHANG)
545 
546 asmlinkage int irix_waitsys(int type, int pid, struct irix5_siginfo *info,
547                             int options, struct rusage *ru)
548 {
549         int flag, retval;
550         DECLARE_WAITQUEUE(wait, current);
551         struct task_struct *tsk;
552         struct task_struct *p;
553         struct list_head *_p;
554 
555         if (!info) {
556                 retval = -EINVAL;
557                 goto out;
558         }
559         retval = verify_area(VERIFY_WRITE, info, sizeof(*info));
560         if(retval)
561                 goto out;
562         if (ru) {
563                 retval = verify_area(VERIFY_WRITE, ru, sizeof(*ru));
564                 if(retval)
565                         goto out;
566         }
567         if (options & ~(W_MASK)) {
568                 retval = -EINVAL;
569                 goto out;
570         }
571         if (type != P_PID && type != P_PGID && type != P_ALL) {
572                 retval = -EINVAL;
573                 goto out;
574         }
575         add_wait_queue(&current->wait_chldexit, &wait);
576 repeat:
577         flag = 0;
578         current->state = TASK_INTERRUPTIBLE;
579         read_lock(&tasklist_lock);
580         tsk = current;
581         list_for_each(_p,&tsk->children) {
582                 p = list_entry(_p,struct task_struct,sibling);
583                 if ((type == P_PID) && p->pid != pid)
584                         continue;
585                 if ((type == P_PGID) && process_group(p) != pid)
586                         continue;
587                 if ((p->exit_signal != SIGCHLD))
588                         continue;
589                 flag = 1;
590                 switch (p->state) {
591                 case TASK_STOPPED:
592                         if (!p->exit_code)
593                                 continue;
594                         if (!(options & (W_TRAPPED|W_STOPPED)) &&
595                             !(p->ptrace & PT_PTRACED))
596                                 continue;
597                         read_unlock(&tasklist_lock);
598 
599                         /* move to end of parent's list to avoid starvation */
600                         write_lock_irq(&tasklist_lock);
601                         remove_parent(p);
602                         add_parent(p, p->parent);
603                         write_unlock_irq(&tasklist_lock);
604                         retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0;
605                         if (!retval && ru) {
606                                 retval |= __put_user(SIGCHLD, &info->sig);
607                                 retval |= __put_user(0, &info->code);
608                                 retval |= __put_user(p->pid, &info->stuff.procinfo.pid);
609                                 retval |= __put_user((p->exit_code >> 8) & 0xff,
610                                            &info->stuff.procinfo.procdata.child.status);
611                                 retval |= __put_user(p->utime, &info->stuff.procinfo.procdata.child.utime);
612                                 retval |= __put_user(p->stime, &info->stuff.procinfo.procdata.child.stime);
613                         }
614                         if (!retval) {
615                                 p->exit_code = 0;
616                         }
617                         goto end_waitsys;
618 
619                 case TASK_ZOMBIE:
620                         current->cutime += p->utime + p->cutime;
621                         current->cstime += p->stime + p->cstime;
622                         if (ru != NULL)
623                                 getrusage(p, RUSAGE_BOTH, ru);
624                         __put_user(SIGCHLD, &info->sig);
625                         __put_user(1, &info->code);      /* CLD_EXITED */
626                         __put_user(p->pid, &info->stuff.procinfo.pid);
627                         __put_user((p->exit_code >> 8) & 0xff,
628                                    &info->stuff.procinfo.procdata.child.status);
629                         __put_user(p->utime,
630                                    &info->stuff.procinfo.procdata.child.utime);
631                         __put_user(p->stime,
632                                    &info->stuff.procinfo.procdata.child.stime);
633                         retval = 0;
634                         if (p->real_parent != p->parent) {
635                                 write_lock_irq(&tasklist_lock);
636                                 remove_parent(p);
637                                 p->parent = p->real_parent;
638                                 add_parent(p, p->parent);
639                                 do_notify_parent(p, SIGCHLD);
640                                 write_unlock_irq(&tasklist_lock);
641                         } else
642                                 release_task(p);
643                         goto end_waitsys;
644                 default:
645                         continue;
646                 }
647                 tsk = next_thread(tsk);
648         }
649         read_unlock(&tasklist_lock);
650         if (flag) {
651                 retval = 0;
652                 if (options & W_NOHANG)
653                         goto end_waitsys;
654                 retval = -ERESTARTSYS;
655                 if (signal_pending(current))
656                         goto end_waitsys;
657                 current->state = TASK_INTERRUPTIBLE;
658                 schedule();
659                 goto repeat;
660         }
661         retval = -ECHILD;
662 end_waitsys:
663         current->state = TASK_RUNNING;
664         remove_wait_queue(&current->wait_chldexit, &wait);
665 
666 out:
667         return retval;
668 }
669 
670 struct irix5_context {
671         u32 flags;
672         u32 link;
673         u32 sigmask[4];
674         struct { u32 sp, size, flags; } stack;
675         int regs[36];
676         u32 fpregs[32];
677         u32 fpcsr;
678         u32 _unused0;
679         u32 _unused1[47];
680         u32 weird_graphics_thing;
681 };
682 
683 asmlinkage int irix_getcontext(struct pt_regs *regs)
684 {
685         int error, i, base = 0;
686         struct irix5_context *ctx;
687         unsigned long flags;
688 
689         if (regs->regs[2] == 1000)
690                 base = 1;
691         ctx = (struct irix5_context *) regs->regs[base + 4];
692 
693 #ifdef DEBUG_SIG
694         printk("[%s:%d] irix_getcontext(%p)\n",
695                current->comm, current->pid, ctx);
696 #endif
697 
698         error = verify_area(VERIFY_WRITE, ctx, sizeof(*ctx));
699         if(error)
700                 goto out;
701         __put_user(current->thread.irix_oldctx, &ctx->link);
702 
703         __copy_to_user(&ctx->sigmask, &current->blocked, sizeof(irix_sigset_t));
704 
705         /* XXX Do sigstack stuff someday... */
706         __put_user(0, &ctx->stack.sp);
707         __put_user(0, &ctx->stack.size);
708         __put_user(0, &ctx->stack.flags);
709 
710         __put_user(0, &ctx->weird_graphics_thing);
711         __put_user(0, &ctx->regs[0]);
712         for (i = 1; i < 32; i++)
713                 __put_user(regs->regs[i], &ctx->regs[i]);
714         __put_user(regs->lo, &ctx->regs[32]);
715         __put_user(regs->hi, &ctx->regs[33]);
716         __put_user(regs->cp0_cause, &ctx->regs[34]);
717         __put_user(regs->cp0_epc, &ctx->regs[35]);
718 
719         flags = 0x0f;
720         if(!current->used_math) {
721                 flags &= ~(0x08);
722         } else {
723                 /* XXX wheee... */
724                 printk("Wheee, no code for saving IRIX FPU context yet.\n");
725         }
726         __put_user(flags, &ctx->flags);
727         error = 0;
728 
729 out:
730         return error;
731 }
732 
733 asmlinkage unsigned long irix_setcontext(struct pt_regs *regs)
734 {
735         int error, base = 0;
736         struct irix5_context *ctx;
737 
738         if(regs->regs[2] == 1000)
739                 base = 1;
740         ctx = (struct irix5_context *) regs->regs[base + 4];
741 
742 #ifdef DEBUG_SIG
743         printk("[%s:%d] irix_setcontext(%p)\n",
744                current->comm, current->pid, ctx);
745 #endif
746 
747         error = verify_area(VERIFY_READ, ctx, sizeof(*ctx));
748         if (error)
749                 goto out;
750 
751         if (ctx->flags & 0x02) {
752                 /* XXX sigstack garbage, todo... */
753                 printk("Wheee, cannot do sigstack stuff in setcontext\n");
754         }
755 
756         if (ctx->flags & 0x04) {
757                 int i;
758 
759                 /* XXX extra control block stuff... todo... */
760                 for(i = 1; i < 32; i++)
761                         regs->regs[i] = ctx->regs[i];
762                 regs->lo = ctx->regs[32];
763                 regs->hi = ctx->regs[33];
764                 regs->cp0_epc = ctx->regs[35];
765         }
766 
767         if (ctx->flags & 0x08) {
768                 /* XXX fpu context, blah... */
769                 printk("Wheee, cannot restore FPU context yet...\n");
770         }
771         current->thread.irix_oldctx = ctx->link;
772         error = regs->regs[2];
773 
774 out:
775         return error;
776 }
777 
778 struct irix_sigstack { unsigned long sp; int status; };
779 
780 asmlinkage int irix_sigstack(struct irix_sigstack *new, struct irix_sigstack *old)
781 {
782         int error;
783 
784 #ifdef DEBUG_SIG
785         printk("[%s:%d] irix_sigstack(%p,%p)\n",
786                current->comm, current->pid, new, old);
787 #endif
788         if(new) {
789                 error = verify_area(VERIFY_READ, new, sizeof(*new));
790                 if(error)
791                         goto out;
792         }
793 
794         if(old) {
795                 error = verify_area(VERIFY_WRITE, old, sizeof(*old));
796                 if(error)
797                         goto out;
798         }
799         error = 0;
800 
801 out:
802         return error;
803 }
804 
805 struct irix_sigaltstack { unsigned long sp; int size; int status; };
806 
807 asmlinkage int irix_sigaltstack(struct irix_sigaltstack *new,
808                                 struct irix_sigaltstack *old)
809 {
810         int error;
811 
812 #ifdef DEBUG_SIG
813         printk("[%s:%d] irix_sigaltstack(%p,%p)\n",
814                current->comm, current->pid, new, old);
815 #endif
816         if (new) {
817                 error = verify_area(VERIFY_READ, new, sizeof(*new));
818                 if(error)
819                         goto out;
820         }
821 
822         if (old) {
823                 error = verify_area(VERIFY_WRITE, old, sizeof(*old));
824                 if(error)
825                         goto out;
826         }
827         error = 0;
828 
829 out:
830         error = 0;
831 
832         return error;
833 }
834 
835 struct irix_procset {
836         int cmd, ltype, lid, rtype, rid;
837 };
838 
839 asmlinkage int irix_sigsendset(struct irix_procset *pset, int sig)
840 {
841         int error;
842 
843         error = verify_area(VERIFY_READ, pset, sizeof(*pset));
844         if(error)
845                 goto out;
846 #ifdef DEBUG_SIG
847         printk("[%s:%d] irix_sigsendset([%d,%d,%d,%d,%d],%d)\n",
848                current->comm, current->pid,
849                pset->cmd, pset->ltype, pset->lid, pset->rtype, pset->rid,
850                sig);
851 #endif
852         error = -EINVAL;
853 
854 out:
855         return error;
856 }
857 

~ [ 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