Example #1
0
void
cpu_lwp_exit(void)
{
	struct thread *td = curthread;
	struct pcb *pcb;

	npxexit();
	pcb = td->td_pcb;

	/* Some i386 functionality was dropped */
	KKASSERT(pcb->pcb_ext == NULL);

	/*
	 * disable all hardware breakpoints
	 */
        if (pcb->pcb_flags & PCB_DBREGS) {
                reset_dbregs();
                pcb->pcb_flags &= ~PCB_DBREGS;
        }
	td->td_gd->gd_cnt.v_swtch++;

	crit_enter_quick(td);
	if (td->td_flags & TDF_TSLEEPQ)
		tsleep_remove(td);
	lwkt_deschedule_self(td);
	lwkt_remove_tdallq(td);
	cpu_thread_exit();
}
Example #2
0
/*
 * Reset registers to default values on exec.
 */
static void
linux_exec_setregs(struct thread *td, struct image_params *imgp, u_long stack)
{
	struct trapframe *regs = td->td_frame;
	struct pcb *pcb = td->td_pcb;

	mtx_lock(&dt_lock);
	if (td->td_proc->p_md.md_ldt != NULL)
		user_ldt_free(td);
	else
		mtx_unlock(&dt_lock);

	pcb->pcb_fsbase = 0;
	pcb->pcb_gsbase = 0;
	clear_pcb_flags(pcb, PCB_32BIT);
	pcb->pcb_initial_fpucw = __LINUX_NPXCW__;
	set_pcb_flags(pcb, PCB_FULL_IRET);

	bzero((char *)regs, sizeof(struct trapframe));
	regs->tf_rip = imgp->entry_addr;
	regs->tf_rsp = stack;
	regs->tf_rflags = PSL_USER | (regs->tf_rflags & PSL_T);
	regs->tf_ss = _udatasel;
	regs->tf_cs = _ucodesel;
	regs->tf_ds = _udatasel;
	regs->tf_es = _udatasel;
	regs->tf_fs = _ufssel;
	regs->tf_gs = _ugssel;
	regs->tf_flags = TF_HASSEGS;

	/*
	 * Reset the hardware debug registers if they were in use.
	 * They won't have any meaning for the newly exec'd process.
	 */
	if (pcb->pcb_flags & PCB_DBREGS) {
		pcb->pcb_dr0 = 0;
		pcb->pcb_dr1 = 0;
		pcb->pcb_dr2 = 0;
		pcb->pcb_dr3 = 0;
		pcb->pcb_dr6 = 0;
		pcb->pcb_dr7 = 0;
		if (pcb == curpcb) {
			/*
			 * Clear the debug registers on the running
			 * CPU, otherwise they will end up affecting
			 * the next process we switch to.
			 */
			reset_dbregs();
		}
		clear_pcb_flags(pcb, PCB_DBREGS);
	}

	/*
	 * Drop the FP state if we hold it, so that the process gets a
	 * clean FP state if it uses the FPU again.
	 */
	fpstate_drop(td);
}
Example #3
0
void
cpu_thread_exit(struct thread *td)
{
	struct pcb *pcb;

	critical_enter();
	if (td == PCPU_GET(fpcurthread))
		fpudrop();
	critical_exit();

	pcb = td->td_pcb;

	/* Disable any hardware breakpoints. */
	if (pcb->pcb_flags & PCB_DBREGS) {
		reset_dbregs();
		clear_pcb_flags(pcb, PCB_DBREGS);
	}
}
Example #4
0
void
cpu_lwp_exit(void)
{
	struct thread *td = curthread;
	struct pcb *pcb;
	struct pcb_ext *ext;

	/*
	 * If we were using a private TSS do a forced-switch to ourselves
	 * to switch back to the common TSS before freeing it.
	 */
	pcb = td->td_pcb;
	if ((ext = pcb->pcb_ext) != NULL) {
		crit_enter();
		pcb->pcb_ext = NULL;
		lwkt_switch_return(td->td_switch(td));
		crit_exit();
		kmem_free(&kernel_map, (vm_offset_t)ext, ctob(IOPAGES + 1));
	}
	user_ldt_free(pcb);
        if (pcb->pcb_flags & PCB_DBREGS) {
                /*
                 * disable all hardware breakpoints
                 */
                reset_dbregs();
                pcb->pcb_flags &= ~PCB_DBREGS;
        }
	td->td_gd->gd_cnt.v_swtch++;

	crit_enter_quick(td);
	if (td->td_flags & TDF_TSLEEPQ)
		tsleep_remove(td);
	lwkt_deschedule_self(td);
	lwkt_remove_tdallq(td);
	cpu_thread_exit();
}
Example #5
0
/*
 * Clear registers on exec
 */
void
exec_setregs(u_long entry, u_long stack, u_long ps_strings)
{
    struct thread *td = curthread;
    struct lwp *lp = td->td_lwp;
    struct trapframe *regs = lp->lwp_md.md_regs;
    struct pcb *pcb = lp->lwp_thread->td_pcb;

    /* was i386_user_cleanup() in NetBSD */
    user_ldt_free(pcb);

    bzero((char *)regs, sizeof(struct trapframe));
    regs->tf_eip = entry;
    regs->tf_esp = stack;
    regs->tf_eflags = PSL_USER | (regs->tf_eflags & PSL_T);
    regs->tf_ss = 0;
    regs->tf_ds = 0;
    regs->tf_es = 0;
    regs->tf_fs = 0;
    regs->tf_gs = 0;
    regs->tf_cs = 0;

    /* PS_STRINGS value for BSD/OS binaries.  It is 0 for non-BSD/OS. */
    regs->tf_ebx = ps_strings;

    /*
     * Reset the hardware debug registers if they were in use.
     * They won't have any meaning for the newly exec'd process.
     */
    if (pcb->pcb_flags & PCB_DBREGS) {
        pcb->pcb_dr0 = 0;
        pcb->pcb_dr1 = 0;
        pcb->pcb_dr2 = 0;
        pcb->pcb_dr3 = 0;
        pcb->pcb_dr6 = 0;
        pcb->pcb_dr7 = 0;
        if (pcb == td->td_pcb) {
            /*
            * Clear the debug registers on the running
             * CPU, otherwise they will end up affecting
             * the next process we switch to.
             */
            reset_dbregs();
        }
        pcb->pcb_flags &= ~PCB_DBREGS;
    }

    /*
     * Initialize the math emulator (if any) for the current process.
     * Actually, just clear the bit that says that the emulator has
     * been initialized.  Initialization is delayed until the process
     * traps to the emulator (if it is done at all) mainly because
     * emulators don't provide an entry point for initialization.
     */
    pcb->pcb_flags &= ~FP_SOFTFP;

    /*
     * note: do not set CR0_TS here.  npxinit() must do it after clearing
     * gd_npxthread.  Otherwise a preemptive interrupt thread may panic
     * in npxdna().
     */
    crit_enter();
#if 0
    load_cr0(rcr0() | CR0_MP);
#endif

#if NNPX > 0
    /* Initialize the npx (if any) for the current process. */
    npxinit();
#endif
    crit_exit();

    /*
     * note: linux emulator needs edx to be 0x0 on entry, which is
     * handled in execve simply by setting the 64 bit syscall
     * return value to 0.
     */
}