void syscall_handler_tt(int sig, struct pt_regs *regs) { void *sc; long result; int syscall; #ifdef CONFIG_SYSCALL_DEBUG int index; index = record_syscall_start(syscall); #endif sc = UPT_SC(®s->regs); SC_START_SYSCALL(sc); syscall_trace(®s->regs, 0); current->thread.nsyscalls++; nsyscalls++; syscall = UPT_SYSCALL_NR(®s->regs); if((syscall >= NR_syscalls) || (syscall < 0)) result = -ENOSYS; else result = EXECUTE_SYSCALL(syscall, regs); /* regs->sc may have changed while the system call ran (there may * have been an interrupt or segfault), so it needs to be refreshed. */ UPT_SC(®s->regs) = sc; SC_SET_SYSCALL_RETURN(sc, result); syscall_trace(®s->regs, 1); #ifdef CONFIG_SYSCALL_DEBUG record_syscall_end(index, result); #endif }
void handle_syscall(struct uml_pt_regs *r) { struct pt_regs *regs = container_of(r, struct pt_regs, regs); long result; int syscall; syscall_trace(r, 0); /* * This should go in the declaration of syscall, but when I do that, * strace -f -c bash -c 'ls ; ls' breaks, sometimes not tracing * children at all, sometimes hanging when bash doesn't see the first * ls exit. * The assembly looks functionally the same to me. This is * gcc version 4.0.1 20050727 (Red Hat 4.0.1-5) * in case it's a compiler bug. */ syscall = UPT_SYSCALL_NR(r); if ((syscall >= NR_SYSCALLS) || (syscall < 0)) result = -ENOSYS; else result = EXECUTE_SYSCALL(syscall, regs); REGS_SET_SYSCALL_RETURN(r->gp, result); syscall_trace(r, 1); }
void handle_syscall(union uml_pt_regs *regs) { long result; int index; index = record_syscall_start(UPT_SYSCALL_NR(regs)); syscall_trace(); result = execute_syscall(regs); REGS_SET_SYSCALL_RETURN(regs->skas.regs, result); if((result == -ERESTARTNOHAND) || (result == -ERESTARTSYS) || (result == -ERESTARTNOINTR)) do_signal(result); syscall_trace(); record_syscall_end(index, result); }
void handle_syscall(union uml_pt_regs *regs) { long result; #ifdef UML_CONFIG_SYSCALL_DEBUG int index; index = record_syscall_start(UPT_SYSCALL_NR(regs)); #endif syscall_trace(regs, 0); result = execute_syscall_skas(regs); REGS_SET_SYSCALL_RETURN(regs->skas.regs, result); syscall_trace(regs, 1); #ifdef UML_CONFIG_SYSCALL_DEBUG record_syscall_end(index, result); #endif }
void do_sys(struct pt_regs *regs) { unsigned long syscallnr, usp; syscall_t syscall; int errno, narg; /* * Compute the return address; */ if (regs->cp0_cause & CAUSEF_BD) { /* * This syscall is in a branch delay slot. Since we don't do * branch delay slot handling we would get a process trying * to do syscalls ever and ever again. So better zap it. */ printk("%s: syscall in branch delay slot.\n", current->comm); current->sig->action[SIGILL-1].sa_handler = NULL; current->blocked &= ~(1<<(SIGILL-1)); send_sig(SIGILL, current, 1); return; } regs->cp0_epc += 4; syscallnr = regs->reg2; if (syscallnr > (__NR_Linux + __NR_Linux_syscalls)) goto illegal_syscall; syscall = sys_call_table[syscallnr]; if (syscall == NULL) goto illegal_syscall; narg = sys_narg_table[syscallnr]; if (narg > 4) { /* * Verify that we can safely get the additional parameters * from the user stack. Of course I could read the params * from unaligned addresses ... Consider this a programming * course caliber .45. */ usp = regs->reg29; if (usp & 3) { printk("unaligned usp\n"); send_sig(SIGSEGV, current, 1); regs->reg2 = EFAULT; regs->reg7 = 1; return; } errno = verify_area(VERIFY_READ, (void *) (usp + 16), (narg - 4) * sizeof(unsigned long)); if (errno < 0) goto bad_syscall; } if ((current->flags & PF_TRACESYS) == 0) { errno = do_syscalls(regs, syscall, narg); if (errno < 0 || current->errno) goto bad_syscall; regs->reg2 = errno; regs->reg7 = 0; } else { syscall_trace(); errno = do_syscalls(regs, syscall, narg); if (errno < 0 || current->errno) { regs->reg2 = -errno; regs->reg7 = 1; } else { regs->reg2 = errno; regs->reg7 = 0; } syscall_trace(); } return; bad_syscall: regs->reg2 = -errno; regs->reg7 = 1; return; illegal_syscall: regs->reg2 = ENOSYS; regs->reg7 = 1; return; }
asmlinkage void irix_sigreturn(struct pt_regs *regs) { struct sigctx_irix5 *context, *magic; unsigned long umask, mask; u64 *fregs; int sig, i, base = 0; sigset_t blocked; if(regs->regs[2] == 1000) base = 1; context = (struct sigctx_irix5 *) regs->regs[base + 4]; magic = (struct sigctx_irix5 *) regs->regs[base + 5]; sig = (int) regs->regs[base + 6]; #ifdef DEBUG_SIG printk("[%s:%d] IRIX sigreturn(scp[%p],ucp[%p],sig[%d])\n", current->comm, current->pid, context, magic, sig); #endif if (!context) context = magic; if (!access_ok(VERIFY_READ, context, sizeof(struct sigctx_irix5))) goto badframe; #ifdef DEBUG_SIG dump_irix5_sigctx(context); #endif __get_user(regs->cp0_epc, &context->pc); umask = context->rmask; mask = 2; for (i = 1; i < 32; i++, mask <<= 1) { if(umask & mask) __get_user(regs->regs[i], &context->regs[i]); } __get_user(regs->hi, &context->hi); __get_user(regs->lo, &context->lo); if ((umask & 1) && context->usedfp) { fregs = (u64 *) ¤t->thread.fpu; for(i = 0; i < 32; i++) fregs[i] = (u64) context->fpregs[i]; __get_user(current->thread.fpu.hard.control, &context->fpcsr); } /* XXX do sigstack crapola here... XXX */ if (__copy_from_user(&blocked, &context->sigset, sizeof(blocked))) goto badframe; sigdelsetmask(&blocked, ~_BLOCKABLE); spin_lock_irq(¤t->sigmask_lock); current->blocked = blocked; recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); /* * Don't let your children do this ... */ if (current->ptrace & PT_TRACESYS) syscall_trace(); __asm__ __volatile__( "move\t$29,%0\n\t" "j\tret_from_sys_call" :/* no outputs */ :"r" (®s)); /* Unreached */ badframe: force_sig(SIGSEGV, current); }