int process_read_regs(struct lwp *l, struct reg *regs) { struct trapframe *tf = process_frame(l); #ifdef VM86 if (tf->tf_eflags & PSL_VM) { regs->r_gs = tf->tf_vm86_gs; regs->r_fs = tf->tf_vm86_fs; regs->r_es = tf->tf_vm86_es; regs->r_ds = tf->tf_vm86_ds; regs->r_eflags = get_vflags(l); } else #endif { regs->r_gs = tf->tf_gs & 0xffff; regs->r_fs = tf->tf_fs & 0xffff; regs->r_es = tf->tf_es & 0xffff; regs->r_ds = tf->tf_ds & 0xffff; regs->r_eflags = tf->tf_eflags; } regs->r_edi = tf->tf_edi; regs->r_esi = tf->tf_esi; regs->r_ebp = tf->tf_ebp; regs->r_ebx = tf->tf_ebx; regs->r_edx = tf->tf_edx; regs->r_ecx = tf->tf_ecx; regs->r_eax = tf->tf_eax; regs->r_eip = tf->tf_eip; regs->r_cs = tf->tf_cs & 0xffff; regs->r_esp = tf->tf_esp; regs->r_ss = tf->tf_ss & 0xffff; return (0); }
static void linux_save_sigcontext(struct lwp *l, struct trapframe *tf, const sigset_t *mask, struct linux_sigcontext *sc) { struct pcb *pcb = lwp_getpcb(l); /* Save register context. */ #ifdef VM86 if (tf->tf_eflags & PSL_VM) { sc->sc_gs = tf->tf_vm86_gs; sc->sc_fs = tf->tf_vm86_fs; sc->sc_es = tf->tf_vm86_es; sc->sc_ds = tf->tf_vm86_ds; sc->sc_eflags = get_vflags(l); } else #endif { sc->sc_gs = tf->tf_gs; sc->sc_fs = tf->tf_fs; sc->sc_es = tf->tf_es; sc->sc_ds = tf->tf_ds; sc->sc_eflags = tf->tf_eflags; } sc->sc_edi = tf->tf_edi; sc->sc_esi = tf->tf_esi; sc->sc_esp = tf->tf_esp; sc->sc_ebp = tf->tf_ebp; sc->sc_ebx = tf->tf_ebx; sc->sc_edx = tf->tf_edx; sc->sc_ecx = tf->tf_ecx; sc->sc_eax = tf->tf_eax; sc->sc_eip = tf->tf_eip; sc->sc_cs = tf->tf_cs; sc->sc_esp_at_signal = tf->tf_esp; sc->sc_ss = tf->tf_ss; sc->sc_err = tf->tf_err; sc->sc_trapno = tf->tf_trapno; sc->sc_cr2 = pcb->pcb_cr2; sc->sc_387 = NULL; /* Save signal stack. */ /* Linux doesn't save the onstack flag in sigframe */ /* Save signal mask. */ native_to_linux_old_sigset(&sc->sc_mask, mask); }
void linux_sendsig(sig_t catcher, int sig, int mask, u_long code, int type, union sigval val) { struct proc *p = curproc; struct trapframe *tf; struct linux_sigframe *fp, frame; struct sigacts *psp = p->p_sigacts; int oonstack; tf = p->p_md.md_regs; oonstack = p->p_sigstk.ss_flags & SS_ONSTACK; /* * Allocate space for the signal handler context. */ if ((p->p_sigstk.ss_flags & SS_DISABLE) == 0 && !oonstack && (psp->ps_sigonstack & sigmask(sig))) { fp = (struct linux_sigframe *)((char *)p->p_sigstk.ss_sp + p->p_sigstk.ss_size - sizeof(struct linux_sigframe)); p->p_sigstk.ss_flags |= SS_ONSTACK; } else { fp = (struct linux_sigframe *)tf->tf_esp - 1; } frame.sf_handler = catcher; frame.sf_sig = bsd_to_linux_sig[sig]; /* * Build the signal context to be used by sigreturn. */ frame.sf_sc.sc_mask = mask; #ifdef VM86 if (tf->tf_eflags & PSL_VM) { frame.sf_sc.sc_gs = tf->tf_vm86_gs; frame.sf_sc.sc_fs = tf->tf_vm86_fs; frame.sf_sc.sc_es = tf->tf_vm86_es; frame.sf_sc.sc_ds = tf->tf_vm86_ds; frame.sf_sc.sc_eflags = get_vflags(p); } else #endif { frame.sf_sc.sc_fs = tf->tf_fs; frame.sf_sc.sc_gs = tf->tf_gs; frame.sf_sc.sc_es = tf->tf_es; frame.sf_sc.sc_ds = tf->tf_ds; frame.sf_sc.sc_eflags = tf->tf_eflags; } frame.sf_sc.sc_edi = tf->tf_edi; frame.sf_sc.sc_esi = tf->tf_esi; frame.sf_sc.sc_ebp = tf->tf_ebp; frame.sf_sc.sc_ebx = tf->tf_ebx; frame.sf_sc.sc_edx = tf->tf_edx; frame.sf_sc.sc_ecx = tf->tf_ecx; frame.sf_sc.sc_eax = tf->tf_eax; frame.sf_sc.sc_eip = tf->tf_eip; frame.sf_sc.sc_cs = tf->tf_cs; frame.sf_sc.sc_esp_at_signal = tf->tf_esp; frame.sf_sc.sc_ss = tf->tf_ss; frame.sf_sc.sc_err = tf->tf_err; frame.sf_sc.sc_trapno = tf->tf_trapno; if (copyout(&frame, fp, sizeof(frame)) != 0) { /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ sigexit(p, SIGILL); /* NOTREACHED */ } /* * Build context to run handler in. */ tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_eip = p->p_sigcode; tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL); tf->tf_eflags &= ~(PSL_T|PSL_D|PSL_VM|PSL_AC); tf->tf_esp = (int)fp; tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL); }
/* * Handle a GP fault that occurred while in VM86 mode. Things that are easy * to handle here are done here (much more efficient than trapping to 32-bit * handler code and then having it restart VM86 mode). */ void vm86_gpfault(struct proc *p, int type) { struct trapframe *tf = p->p_md.md_regs; union sigval sv; /* * we want to fetch some stuff from the current user virtual * address space for checking. remember that the frame's * segment selectors are real-mode style selectors. */ u_long cs, ip, ss, sp; u_char tmpbyte; int trace; cs = CS(tf) << 4; ip = IP(tf); ss = SS(tf) << 4; sp = SP(tf); trace = tf->tf_eflags & PSL_T; /* * For most of these, we must set all the registers before calling * macros/functions which might do a vm86_return. */ tmpbyte = getbyte(cs, ip); IP(tf) = ip; switch (tmpbyte) { case CLI: /* simulate handling of IF */ clr_vif(p); break; case STI: /* simulate handling of IF. * XXX the i386 enables interrupts one instruction later. * code here is wrong, but much simpler than doing it Right. */ set_vif(p); break; case INTxx: /* try fast intxx, or return to 32bit mode to handle it. */ tmpbyte = getbyte(cs, ip); IP(tf) = ip; fast_intxx(p, tmpbyte); break; case INTO: if (tf->tf_eflags & PSL_V) fast_intxx(p, 4); break; case PUSHF: putword(ss, sp, get_vflags_short(p)); SP(tf) = sp; break; case IRET: IP(tf) = getword(ss, sp); CS(tf) = getword(ss, sp); case POPF: set_vflags_short(p, getword(ss, sp)); SP(tf) = sp; break; case OPSIZ: tmpbyte = getbyte(cs, ip); IP(tf) = ip; switch (tmpbyte) { case PUSHF: putdword(ss, sp, get_vflags(p) & ~PSL_VM); SP(tf) = sp; break; case IRET: IP(tf) = getdword(ss, sp); CS(tf) = getdword(ss, sp); case POPF: set_vflags(p, getdword(ss, sp) | PSL_VM); SP(tf) = sp; break; default: IP(tf) -= 2; goto bad; } break; case LOCK: default: IP(tf) -= 1; goto bad; } if (trace && tf->tf_eflags & PSL_VM) { sv.sival_int = 0; trapsignal(p, SIGTRAP, T_TRCTRAP, TRAP_TRACE, sv); } return; bad: vm86_return(p, VM86_UNKNOWN); return; }
void svr4_getcontext(struct proc *p, struct svr4_ucontext *uc, int mask, int oonstack) { struct trapframe *tf = p->p_md.md_regs; struct sigacts *psp = p->p_sigacts; svr4_greg_t *r = uc->uc_mcontext.greg; struct svr4_sigaltstack *s = &uc->uc_stack; struct sigaltstack *sf = &psp->ps_sigstk; bzero(uc, sizeof(struct svr4_ucontext)); /* * Set the general purpose registers */ #ifdef VM86 if (tf->tf_eflags & PSL_VM) { r[SVR4_X86_GS] = tf->tf_vm86_gs; r[SVR4_X86_FS] = tf->tf_vm86_fs; r[SVR4_X86_ES] = tf->tf_vm86_es; r[SVR4_X86_DS] = tf->tf_vm86_ds; r[SVR4_X86_EFL] = get_vflags(p); } else #endif { r[SVR4_X86_FS] = tf->tf_fs; r[SVR4_X86_GS] = tf->tf_gs; r[SVR4_X86_ES] = tf->tf_es; r[SVR4_X86_DS] = tf->tf_ds; r[SVR4_X86_EFL] = tf->tf_eflags; } r[SVR4_X86_EDI] = tf->tf_edi; r[SVR4_X86_ESI] = tf->tf_esi; r[SVR4_X86_EBP] = tf->tf_ebp; r[SVR4_X86_ESP] = tf->tf_esp; r[SVR4_X86_EBX] = tf->tf_ebx; r[SVR4_X86_EDX] = tf->tf_edx; r[SVR4_X86_ECX] = tf->tf_ecx; r[SVR4_X86_EAX] = tf->tf_eax; r[SVR4_X86_TRAPNO] = 0; r[SVR4_X86_ERR] = 0; r[SVR4_X86_EIP] = tf->tf_eip; r[SVR4_X86_CS] = tf->tf_cs; r[SVR4_X86_UESP] = 0; r[SVR4_X86_SS] = tf->tf_ss; /* * Set the signal stack */ bsd_to_svr4_sigaltstack(sf, s); /* * Set the signal mask */ bsd_to_svr4_sigset(&mask, &uc->uc_sigmask); /* * Set the flags */ uc->uc_flags = SVR4_UC_ALL; }
/* * Send an interrupt to process. * * Stack is set up to allow sigcode stored * in u. to call routine, followed by kcall * to sigreturn routine below. After sigreturn * resets the signal mask, the stack, and the * frame pointer, it returns to the user * specified pc, psl. */ void freebsd_sendsig(const ksiginfo_t *ksi, const sigset_t *mask) { int sig = ksi->ksi_signo; u_long code = KSI_TRAPCODE(ksi); struct lwp *l = curlwp; struct proc *p = l->l_proc; int onstack, error; struct freebsd_sigframe *fp = getframe(l, sig, &onstack), frame; sig_t catcher = SIGACTION(p, sig).sa_handler; struct trapframe *tf = l->l_md.md_regs; fp--; /* Build stack frame for signal trampoline. */ frame.sf_signum = sig; frame.sf_code = code; frame.sf_scp = &fp->sf_sc; frame.sf_addr = (char *)rcr2(); frame.sf_handler = catcher; /* Save context. */ #ifdef VM86 if (tf->tf_eflags & PSL_VM) { frame.sf_sc.sc_gs = tf->tf_vm86_gs; frame.sf_sc.sc_fs = tf->tf_vm86_fs; frame.sf_sc.sc_es = tf->tf_vm86_es; frame.sf_sc.sc_ds = tf->tf_vm86_ds; frame.sf_sc.sc_efl = get_vflags(l); (*p->p_emul->e_syscall_intern)(p); } else #endif { frame.sf_sc.sc_gs = tf->tf_gs; frame.sf_sc.sc_fs = tf->tf_fs; frame.sf_sc.sc_es = tf->tf_es; frame.sf_sc.sc_ds = tf->tf_ds; frame.sf_sc.sc_efl = tf->tf_eflags; } frame.sf_sc.sc_edi = tf->tf_edi; frame.sf_sc.sc_esi = tf->tf_esi; frame.sf_sc.sc_ebp = tf->tf_ebp; frame.sf_sc.sc_isp = 0; /* don't have to pass kernel sp to user. */ frame.sf_sc.sc_ebx = tf->tf_ebx; frame.sf_sc.sc_edx = tf->tf_edx; frame.sf_sc.sc_ecx = tf->tf_ecx; frame.sf_sc.sc_eax = tf->tf_eax; frame.sf_sc.sc_eip = tf->tf_eip; frame.sf_sc.sc_cs = tf->tf_cs; frame.sf_sc.sc_esp = tf->tf_esp; frame.sf_sc.sc_ss = tf->tf_ss; /* Save signal stack. */ frame.sf_sc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK; /* Save signal mask. */ /* XXX freebsd_osigcontext compat? */ frame.sf_sc.sc_mask = *mask; sendsig_reset(l, sig); mutex_exit(p->p_lock); error = copyout(&frame, fp, sizeof(frame)); mutex_enter(p->p_lock); if (error != 0) { /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ sigexit(l, SIGILL); /* NOTREACHED */ } buildcontext(l, GUCODEBIG_SEL, p->p_sigctx.ps_sigcode, fp); /* Remember that we're now on the signal stack. */ if (onstack) l->l_sigstk.ss_flags |= SS_ONSTACK; }
/* * Send an interrupt to process. * * Stack is set up to allow sigcode stored * in u. to call routine, followed by kcall * to sigreturn routine below. After sigreturn * resets the signal mask, the stack, and the * frame pointer, it returns to the user * specified pc, psl. */ void sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *mask) { struct lwp *l = curlwp; struct proc *p = l->l_proc; struct pmap *pmap = vm_map_pmap(&p->p_vmspace->vm_map); int sel = pmap->pm_hiexec > I386_MAX_EXE_ADDR ? GUCODEBIG_SEL : GUCODE_SEL; struct sigacts *ps = p->p_sigacts; struct trapframe *tf = l->l_md.md_regs; int onstack, error; int sig = ksi->ksi_signo; u_long code = KSI_TRAPCODE(ksi); struct sigframe_sigcontext *fp = getframe(l, sig, &onstack), frame; sig_t catcher = SIGACTION(p, sig).sa_handler; fp--; /* Build stack frame for signal trampoline. */ switch (ps->sa_sigdesc[sig].sd_vers) { case 0: /* legacy on-stack sigtramp */ frame.sf_ra = (int)p->p_sigctx.ps_sigcode; break; case 1: frame.sf_ra = (int)ps->sa_sigdesc[sig].sd_tramp; break; default: /* Don't know what trampoline version; kill it. */ sigexit(l, SIGILL); } frame.sf_signum = sig; frame.sf_code = code; frame.sf_scp = &fp->sf_sc; /* Save register context. */ #ifdef VM86 if (tf->tf_eflags & PSL_VM) { frame.sf_sc.sc_gs = tf->tf_vm86_gs; frame.sf_sc.sc_fs = tf->tf_vm86_fs; frame.sf_sc.sc_es = tf->tf_vm86_es; frame.sf_sc.sc_ds = tf->tf_vm86_ds; frame.sf_sc.sc_eflags = get_vflags(l); (*p->p_emul->e_syscall_intern)(p); } else #endif { frame.sf_sc.sc_gs = tf->tf_gs; frame.sf_sc.sc_fs = tf->tf_fs; frame.sf_sc.sc_es = tf->tf_es; frame.sf_sc.sc_ds = tf->tf_ds; frame.sf_sc.sc_eflags = tf->tf_eflags; } frame.sf_sc.sc_edi = tf->tf_edi; frame.sf_sc.sc_esi = tf->tf_esi; frame.sf_sc.sc_ebp = tf->tf_ebp; frame.sf_sc.sc_ebx = tf->tf_ebx; frame.sf_sc.sc_edx = tf->tf_edx; frame.sf_sc.sc_ecx = tf->tf_ecx; frame.sf_sc.sc_eax = tf->tf_eax; frame.sf_sc.sc_eip = tf->tf_eip; frame.sf_sc.sc_cs = tf->tf_cs; frame.sf_sc.sc_esp = tf->tf_esp; frame.sf_sc.sc_ss = tf->tf_ss; frame.sf_sc.sc_trapno = tf->tf_trapno; frame.sf_sc.sc_err = tf->tf_err; /* Save signal stack. */ frame.sf_sc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK; /* Save signal mask. */ frame.sf_sc.sc_mask = *mask; #ifdef COMPAT_13 /* * XXX We always have to save an old style signal mask because * XXX we might be delivering a signal to a process which will * XXX escape from the signal in a non-standard way and invoke * XXX sigreturn() directly. */ native_sigset_to_sigset13(mask, &frame.sf_sc.__sc_mask13); #endif sendsig_reset(l, sig); mutex_exit(p->p_lock); error = copyout(&frame, fp, sizeof(frame)); mutex_enter(p->p_lock); if (error != 0) { /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ sigexit(l, SIGILL); /* NOTREACHED */ } int svufpu = l->l_md.md_flags & MDL_USEDFPU; buildcontext(l, sel, catcher, fp); l->l_md.md_flags |= svufpu; /* Remember that we're now on the signal stack. */ if (onstack) l->l_sigstk.ss_flags |= SS_ONSTACK; }