示例#1
0
void
cpu_lwp_free(struct lwp *l, int proc)
{

	if (l->l_addr->u_pcb.pcb_fpcpu != NULL)
		fpusave_proc(l, 0);
}
示例#2
0
文件: vm_machdep.c 项目: MarginC/kame
void
cpu_swapout(struct proc *p)
{

	/*
	 * Make sure we save the FP state before the user area vanishes.
	 */
	fpusave_proc(p, 1);
}
示例#3
0
/*
 * Finish a fork operation, with process p2 nearly set up.
 * Copy and update the kernel stack and pcb, making the child
 * ready to run, and marking it so that it can return differently
 * than the parent.  Returns 1 in the child process, 0 in the parent.
 */
void
cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize,
    void (*func)(void *), void *arg)
{
	struct pcb *pcb = &p2->p_addr->u_pcb;
	struct trapframe *tf;
	struct switchframe *sf;

	/*
	 * If fpuproc != p1, then the fpu h/w state is irrelevant and the
	 * state had better already be in the pcb.  This is true for forks
	 * but not for dumps.
	 *
	 * If fpuproc == p1, then we have to save the fpu h/w state to
	 * p1's pcb so that we can copy it.
	 */
	if (p1->p_addr->u_pcb.pcb_fpcpu != NULL)
		fpusave_proc(p1, 1);

	p2->p_md.md_flags = p1->p_md.md_flags;

#ifdef DIAGNOSTIC
	if (p1 != curproc && p1 != &proc0)
		panic("cpu_fork: curproc");
#endif
	*pcb = p1->p_addr->u_pcb;

	/*
	 * Activate the address space.
	 */
	pmap_activate(p2);

	/* Record where this process's kernel stack is */
	pcb->pcb_kstack = (u_int64_t)p2->p_addr + USPACE - 16;

	/*
	 * Copy the trapframe.
	 */
	p2->p_md.md_regs = tf = (struct trapframe *)pcb->pcb_kstack - 1;
	*tf = *p1->p_md.md_regs;

	setredzone(p2);

	/*
	 * If specified, give the child a different stack.
	 */
	if (stack != NULL)
		tf->tf_rsp = (u_int64_t)stack + stacksize;

	sf = (struct switchframe *)tf - 1;
	sf->sf_r12 = (u_int64_t)func;
	sf->sf_r13 = (u_int64_t)arg;
	sf->sf_rip = (u_int64_t)proc_trampoline;
	pcb->pcb_rsp = (u_int64_t)sf;
	pcb->pcb_rbp = 0;
}
示例#4
0
/*
 * cpu_exit is called as the last action during exit.
 *
 * We clean up a little and then call sched_exit() with the old proc as an
 * argument.
 */
void
cpu_exit(struct proc *p)
{

	/* If we were using the FPU, forget about it. */
	if (p->p_addr->u_pcb.pcb_fpcpu != NULL)
		fpusave_proc(p, 0);

	pmap_deactivate(p);
	sched_exit(p);
}
int
process_write_fpregs(struct proc *p, struct fpreg *regs)
{
	struct fxsave64 *frame = process_fpframe(p);

	if (p->p_md.md_flags & MDP_USEDFPU) {
		fpusave_proc(p, 0);
	} else {
		p->p_md.md_flags |= MDP_USEDFPU;
	}

	memcpy(frame, &regs->fxstate, sizeof(*regs));
	frame->fx_mxcsr &= fpu_mxcsr_mask;
	return (0);
}
示例#6
0
/*
 * cpu_exit is called as the last action during exit.
 *
 * We clean up a little and then call sched_exit() with the old proc as an
 * argument.
 */
void
cpu_exit(struct proc *p)
{

	/* If we were using the FPU, forget about it. */
	if (p->p_addr->u_pcb.pcb_fpcpu != NULL)
		fpusave_proc(p, 0);

	if (p->p_md.md_flags & MDP_USEDMTRR)
		mtrr_clean(p);

	pmap_deactivate(p);
	tss_free(p->p_md.md_tss_sel);
	sched_exit(p);
}
示例#7
0
文件: vm_machdep.c 项目: MarginC/kame
/*
 * cpu_exit is called as the last action during exit.
 *
 * We clean up a little and then call switch_exit() with the old proc as an
 * argument.  switch_exit() first switches to proc0's context, and finally
 * jumps into switch() to wait for another process to wake up.
 */
void
cpu_exit(struct proc *p)
{

	/* If we were using the FPU, forget about it. */
	if (p->p_addr->u_pcb.pcb_fpcpu != NULL)
		fpusave_proc(p, 0);

	if (p->p_md.md_flags & MDP_USEDMTRR)
		mtrr_clean(p);

	/*
	 * No need to do user LDT cleanup here; it's handled in
	 * pmap_destroy().
	 */

	uvmexp.swtch++;
	switch_exit(p, exit2);
}
示例#8
0
/*
 * System call to cleanup state after a signal
 * has been taken.  Reset signal mask and
 * stack state from context left by sendsig (above).
 * Return to previous pc and psl as specified by
 * context left by sendsig. Check carefully to
 * make sure that the user has not modified the
 * psl to gain improper privileges or to cause
 * a machine fault.
 */
int
sys_sigreturn(struct proc *p, void *v, register_t *retval)
{
	struct sys_sigreturn_args /* {
		syscallarg(struct sigcontext *) sigcntxp;
	} */ *uap = v;
	struct sigcontext *scp, ksc;
	struct trapframe *tf = p->p_md.md_regs;
	int error;

	scp = SCARG(uap, sigcntxp);
#ifdef DEBUG
	if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
		printf("sigreturn: pid %d, scp %p\n", p->p_pid, scp);
#endif
	if ((error = copyin((caddr_t)scp, &ksc, sizeof ksc)))
		return (error);

	if (((ksc.sc_rflags ^ tf->tf_rflags) & PSL_USERSTATIC) != 0 ||
	    !USERMODE(ksc.sc_cs, ksc.sc_eflags))
		return (EINVAL);

	if (p->p_md.md_flags & MDP_USEDFPU)
		fpusave_proc(p, 0);

	if (ksc.sc_fpstate && (error = copyin(ksc.sc_fpstate,
	    &p->p_addr->u_pcb.pcb_savefpu.fp_fxsave, sizeof (struct fxsave64))))
		return (error);

	ksc.sc_trapno = tf->tf_trapno;
	ksc.sc_err = tf->tf_err;
	bcopy(&ksc, tf, sizeof(*tf));

	/* Restore signal stack. */
	if (ksc.sc_onstack)
		p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK;
	else
		p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
	p->p_sigmask = ksc.sc_mask & ~sigcantmask;

	return (EJUSTRETURN);
}
示例#9
0
/*
 * Clear registers on exec
 */
void
setregs(struct proc *p, struct exec_package *pack, u_long stack,
    register_t *retval)
{
	struct pcb *pcb = &p->p_addr->u_pcb;
	struct trapframe *tf;

	/* If we were using the FPU, forget about it. */
	if (p->p_addr->u_pcb.pcb_fpcpu != NULL)
		fpusave_proc(p, 0);

#ifdef USER_LDT
	pmap_ldt_cleanup(p);
#endif

	p->p_md.md_flags &= ~MDP_USEDFPU;
	pcb->pcb_flags = 0;
	pcb->pcb_savefpu.fp_fxsave.fx_fcw = __INITIAL_NPXCW__;
	pcb->pcb_savefpu.fp_fxsave.fx_mxcsr = __INITIAL_MXCSR__;
	pcb->pcb_savefpu.fp_fxsave.fx_mxcsr_mask = __INITIAL_MXCSR_MASK__;

	tf = p->p_md.md_regs;
	tf->tf_ds = LSEL(LUDATA_SEL, SEL_UPL);
	tf->tf_es = LSEL(LUDATA_SEL, SEL_UPL);
	tf->tf_fs = LSEL(LUDATA_SEL, SEL_UPL);
	tf->tf_gs = LSEL(LUDATA_SEL, SEL_UPL);
	tf->tf_rdi = 0;
	tf->tf_rsi = 0;
	tf->tf_rbp = 0;
	tf->tf_rbx = 0;
	tf->tf_rdx = 0;
	tf->tf_rcx = 0;
	tf->tf_rax = 0;
	tf->tf_rip = pack->ep_entry;
	tf->tf_cs = LSEL(LUCODE_SEL, SEL_UPL);
	tf->tf_rflags = PSL_USERSET;
	tf->tf_rsp = stack;
	tf->tf_ss = LSEL(LUDATA_SEL, SEL_UPL);

	retval[1] = 0;
}
示例#10
0
int
process_read_fpregs(struct proc *p, struct fpreg *regs)
{
	struct fxsave64 *frame = process_fpframe(p);

	if (p->p_md.md_flags & MDP_USEDFPU) {
		fpusave_proc(p, 1);
	} else {
		/* Fake a FNINIT. */
		memset(frame, 0, sizeof(*regs));
		frame->fx_fcw = __INITIAL_NPXCW__;
		frame->fx_fsw = 0x0000;
		frame->fx_ftw = 0xff;
		frame->fx_mxcsr = __INITIAL_MXCSR__;
		frame->fx_mxcsr_mask = fpu_mxcsr_mask;
		p->p_md.md_flags |= MDP_USEDFPU;
	}

	memcpy(&regs->fxstate, frame, sizeof(*regs));
	return (0);
}
示例#11
0
/*
 * Dump the machine specific header information at the start of a core dump.
 */
int
cpu_coredump(struct lwp *l, void *iocookie, struct core *chdr)
{
	int error;
	struct md_coredump cpustate;
	struct coreseg cseg;

	if (iocookie == NULL) {
		CORE_SETMAGIC(*chdr, COREMAGIC, MID_MACHINE, 0);
		chdr->c_hdrsize = ALIGN(sizeof(*chdr));
		chdr->c_seghdrsize = ALIGN(sizeof(cseg));
		chdr->c_cpusize = sizeof(cpustate);
		chdr->c_nseg++;
		return 0;
	}

	cpustate.md_tf = *l->l_md.md_tf;
	cpustate.md_tf.tf_regs[FRAME_SP] = alpha_pal_rdusp();	/* XXX */
	if (l->l_md.md_flags & MDP_FPUSED) {
		if (l->l_addr->u_pcb.pcb_fpcpu != NULL)
			fpusave_proc(l, 1);
		cpustate.md_fpstate = l->l_addr->u_pcb.pcb_fp;
	} else
		memset(&cpustate.md_fpstate, 0, sizeof(cpustate.md_fpstate));

	CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_MACHINE, CORE_CPU);
	cseg.c_addr = 0;
	cseg.c_size = chdr->c_cpusize;

	error = coredump_write(iocookie, UIO_SYSSPACE, &cseg,
	    chdr->c_seghdrsize);
	if (error)
		return error;

	return coredump_write(iocookie, UIO_SYSSPACE, &cpustate,
	    sizeof(cpustate));
}
示例#12
0
void
sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *mask)
{
	struct lwp *l = curlwp;
	struct proc *p = l->l_proc;
	struct sigacts *ps = p->p_sigacts;
	int onstack, sig = ksi->ksi_signo;
	struct sigframe_sigcontext *fp, frame;
	struct trapframe *tf;
	sig_t catcher = SIGACTION(p, sig).sa_handler;

	tf = l->l_md.md_tf;
	fp = getframe(l, sig, &onstack), frame;
	fp--;

#ifdef DEBUG
	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
		printf("sendsig_sigcontext(%d): sig %d ssp %p usp %p\n",
		       p->p_pid, sig, &onstack, fp);
#endif

	/* Build stack frame for signal trampoline. */
	frame.sf_sc.sc_pc = tf->tf_regs[FRAME_PC];
	frame.sf_sc.sc_ps = tf->tf_regs[FRAME_PS];

	/* Save register context. */
	frametoreg(tf, (struct reg *)frame.sf_sc.sc_regs);
	frame.sf_sc.sc_regs[R_ZERO] = 0xACEDBADE;	/* magic number */
	frame.sf_sc.sc_regs[R_SP] = alpha_pal_rdusp();

 	/* save the floating-point state, if necessary, then copy it. */
	if (l->l_addr->u_pcb.pcb_fpcpu != NULL)
		fpusave_proc(l, 1);
	frame.sf_sc.sc_ownedfp = l->l_md.md_flags & MDP_FPUSED;
	memcpy((struct fpreg *)frame.sf_sc.sc_fpregs, &l->l_addr->u_pcb.pcb_fp,
	    sizeof(struct fpreg));
	frame.sf_sc.sc_fp_control = alpha_read_fp_c(l);
	memset(frame.sf_sc.sc_reserved, 0, sizeof frame.sf_sc.sc_reserved);
	memset(frame.sf_sc.sc_xxx, 0, sizeof frame.sf_sc.sc_xxx); /* XXX */

	/* Save signal stack. */
	frame.sf_sc.sc_onstack = p->p_sigctx.ps_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.
	 */
	{
		/* Note: it's a long in the stack frame. */
		sigset13_t mask13;

		native_sigset_to_sigset13(mask, &mask13);
		frame.sf_sc.__sc_mask13 = mask13;
	}
#endif

#ifdef COMPAT_OSF1
	/*
	 * XXX Create an OSF/1-style sigcontext and associated goo.
	 */
#endif

	if (copyout(&frame, (caddr_t)fp, sizeof(frame)) != 0) {
		/*
		 * Process has trashed its stack; give it an illegal
		 * instruction to halt it in its tracks.
		 */
#ifdef DEBUG
		if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
			printf("sendsig_sigcontext(%d): copyout failed on sig %d\n",
			       p->p_pid, sig);
#endif
		sigexit(l, SIGILL);
		/* NOTREACHED */
	}
#ifdef DEBUG
	if (sigdebug & SDB_FOLLOW)
		printf("sendsig_sigcontext(%d): sig %d usp %p code %x\n",
		       p->p_pid, sig, fp, ksi->ksi_code);
#endif

	/*
	 * Set up the registers to directly invoke the signal handler.  The
	 * signal trampoline is then used to return from the signal.  Note
	 * the trampoline version numbers are coordinated with machine-
	 * dependent code in libc.
	 */
	switch (ps->sa_sigdesc[sig].sd_vers) {
	case 0:		/* legacy on-stack sigtramp */
		buildcontext(l,(void *)catcher,
			     (void *)p->p_sigctx.ps_sigcode,
			     (void *)fp);
		break;
	case 1:
		buildcontext(l,(void *)catcher,
			     (void *)ps->sa_sigdesc[sig].sd_tramp,
			     (void *)fp);
		break;

	default:
		/* Don't know what trampoline version; kill it. */
		sigexit(l, SIGILL);
	}

	/* sigcontext specific trap frame */
	tf->tf_regs[FRAME_A0] = sig;

	/* tf->tf_regs[FRAME_A1] = ksi->ksi_code; */
	tf->tf_regs[FRAME_A1] = KSI_TRAPCODE(ksi);
	tf->tf_regs[FRAME_A2] = (u_int64_t)&fp->sf_sc;

	/* Remember that we're now on the signal stack. */
	if (onstack)
		p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK;

#ifdef DEBUG
	if (sigdebug & SDB_FOLLOW)
		printf("sendsig(%d): pc %lx, catcher %lx\n", p->p_pid,
		    tf->tf_regs[FRAME_PC], tf->tf_regs[FRAME_A3]);
	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
		printf("sendsig(%d): sig %d returns\n",
		    p->p_pid, sig);
#endif
}
示例#13
0
/*
 * Finish a fork operation, with process p2 nearly set up.
 * Copy and update the pcb and trap frame, making the child ready to run.
 * 
 * Rig the child's kernel stack so that it will start out in
 * lwp_trampoline() and call child_return() with p2 as an
 * argument. This causes the newly-created child process to go
 * directly to user level with an apparent return value of 0 from
 * fork(), while the parent process returns normally.
 *
 * p1 is the process being forked; if p1 == &proc0, we are creating
 * a kernel thread, and the return path and argument are specified with
 * `func' and `arg'.
 *
 * If an alternate user-level stack is requested (with non-zero values
 * in both the stack and stacksize args), set up the user stack pointer
 * accordingly.
 */
void
cpu_lwp_fork(struct lwp *l1, struct lwp *l2, void *stack, size_t stacksize,
    void (*func)(void *), void *arg)
{
	struct user *up = l2->l_addr;

	l2->l_md.md_tf = l1->l_md.md_tf;
	l2->l_md.md_flags = l1->l_md.md_flags & (MDP_FPUSED | MDP_FP_C);
	l2->l_md.md_astpending = 0;

	/*
	 * Cache the physical address of the pcb, so we can
	 * swap to it easily.
	 */
	l2->l_md.md_pcbpaddr = (void *)vtophys((vaddr_t)&up->u_pcb);

	/*
	 * Copy floating point state from the FP chip to the PCB
	 * if this process has state stored there.
	 */
	if (l1->l_addr->u_pcb.pcb_fpcpu != NULL)
		fpusave_proc(l1, 1);

	/*
	 * Copy pcb and user stack pointer from proc p1 to p2.
	 * If specificed, give the child a different stack.
	 */
	l2->l_addr->u_pcb = l1->l_addr->u_pcb;
	if (stack != NULL)
		l2->l_addr->u_pcb.pcb_hw.apcb_usp = (u_long)stack + stacksize;
	else
		l2->l_addr->u_pcb.pcb_hw.apcb_usp = alpha_pal_rdusp();
	simple_lock_init(&l2->l_addr->u_pcb.pcb_fpcpu_slock);

	/*
	 * Arrange for a non-local goto when the new process
	 * is started, to resume here, returning nonzero from setjmp.
	 */
#ifdef DIAGNOSTIC
	/*
	 * If l1 != curlwp && l1 == &lwp0, we are creating a kernel
	 * thread.
	 */
	if (l1 != curlwp && l1 != &lwp0)
		panic("cpu_lwp_fork: curlwp");
#endif

	/*
	 * create the child's kernel stack, from scratch.
	 */
	{
		struct trapframe *l2tf;

		/*
		 * Pick a stack pointer, leaving room for a trapframe;
		 * copy trapframe from parent so return to user mode
		 * will be to right address, with correct registers.
		 */
		l2tf = l2->l_md.md_tf = (struct trapframe *)
		    ((char *)l2->l_addr + USPACE - sizeof(struct trapframe));
		memcpy(l2->l_md.md_tf, l1->l_md.md_tf,
		    sizeof(struct trapframe));

		/*
		 * Set up return-value registers as fork() libc stub expects.
		 */
		l2tf->tf_regs[FRAME_V0] = l1->l_proc->p_pid; /* parent's pid */
		l2tf->tf_regs[FRAME_A3] = 0;		/* no error */
		l2tf->tf_regs[FRAME_A4] = 1;		/* is child */

		cpu_setfunc(l2, func, arg);
	}
}
示例#14
0
/*
 * 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(sig_t catcher, int sig, int mask, u_long code, int type,
    union sigval val)
{
	struct proc *p = curproc;
	struct trapframe *tf = p->p_md.md_regs;
	struct sigacts * psp = p->p_sigacts;
	struct sigcontext ksc;
	siginfo_t ksi;
	register_t sp, scp, sip;
	u_long sss;

#ifdef DEBUG
	if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
		printf("sendsig: %s[%d] sig %d catcher %p\n",
		    p->p_comm, p->p_pid, sig, catcher);
#endif

	bcopy(tf, &ksc, sizeof(*tf));
	ksc.sc_onstack = psp->ps_sigstk.ss_flags & SS_ONSTACK;
	ksc.sc_mask = mask;
	ksc.sc_fpstate = NULL;

	/* Allocate space for the signal handler context. */
	if ((psp->ps_flags & SAS_ALTSTACK) && !ksc.sc_onstack &&
	    (psp->ps_sigonstack & sigmask(sig))) {
		sp = (register_t)psp->ps_sigstk.ss_sp + psp->ps_sigstk.ss_size;
		psp->ps_sigstk.ss_flags |= SS_ONSTACK;
	} else
		sp = tf->tf_rsp - 128;

	sp &= ~15ULL;	/* just in case */
	sss = (sizeof(ksc) + 15) & ~15;

	if (p->p_md.md_flags & MDP_USEDFPU) {
		fpusave_proc(p, 1);
		sp -= sizeof(struct fxsave64);
		ksc.sc_fpstate = (struct fxsave64 *)sp;
		if (copyout(&p->p_addr->u_pcb.pcb_savefpu.fp_fxsave,
		    (void *)sp, sizeof(struct fxsave64)))
			sigexit(p, SIGILL);
	}

	sip = 0;
	if (psp->ps_siginfo & sigmask(sig)) {
		sip = sp - ((sizeof(ksi) + 15) & ~15);
		sss += (sizeof(ksi) + 15) & ~15;

		initsiginfo(&ksi, sig, code, type, val);
		if (copyout(&ksi, (void *)sip, sizeof(ksi)))
			sigexit(p, SIGILL);
	}
	scp = sp - sss;

	if (copyout(&ksc, (void *)scp, sizeof(ksc)))
		sigexit(p, SIGILL);

	/*
	 * Build context to run handler in.
	 */
	tf->tf_ds = LSEL(LUDATA_SEL, SEL_UPL);
	tf->tf_es = LSEL(LUDATA_SEL, SEL_UPL);
	tf->tf_fs = LSEL(LUDATA_SEL, SEL_UPL);
	tf->tf_gs = LSEL(LUDATA_SEL, SEL_UPL);

	tf->tf_rax = (u_int64_t)catcher;
	tf->tf_rdi = sig;
	tf->tf_rsi = sip;
	tf->tf_rdx = scp;

	tf->tf_rip = (u_int64_t)p->p_sigcode;
	tf->tf_cs = LSEL(LUCODE_SEL, SEL_UPL);
	tf->tf_rflags &= ~(PSL_T|PSL_VM|PSL_AC);
	tf->tf_rsp = scp;
	tf->tf_ss = LSEL(LUDATA_SEL, SEL_UPL);

#ifdef DEBUG
	if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
		printf("sendsig(%d): pc 0x%x, catcher 0x%x\n", p->p_pid,
		    tf->tf_rip, tf->tf_rax);
#endif
}
示例#15
0
文件: vm_machdep.c 项目: MarginC/kame
/*
 * Finish a fork operation, with process p2 nearly set up.
 * Copy and update the kernel stack and pcb, making the child
 * ready to run, and marking it so that it can return differently
 * than the parent.  Returns 1 in the child process, 0 in the parent.
 * We currently double-map the user area so that the stack is at the same
 * address in each process; in the future we will probably relocate
 * the frame pointers on the stack after copying.
 */
void
cpu_fork(struct proc *p1, struct proc *p2, void *stack, size_t stacksize,
    void (*func)(void *), void *arg)
{
	struct pcb *pcb = &p2->p_addr->u_pcb;
	struct trapframe *tf;
	struct switchframe *sf;

	/*
	 * If fpuproc != p1, then the fpu h/w state is irrelevant and the
	 * state had better already be in the pcb.  This is true for forks
	 * but not for dumps.
	 *
	 * If fpuproc == p1, then we have to save the fpu h/w state to
	 * p1's pcb so that we can copy it.
	 */
	if (p1->p_addr->u_pcb.pcb_fpcpu != NULL)
		fpusave_proc(p1, 1);

	p2->p_md.md_flags = p1->p_md.md_flags;
	syscall_intern(p2);

	/* Copy pcb from proc p1 to p2. */
	if (p1 == curproc) {
		/* Sync the PCB before we copy it. */
		savectx(curpcb);
	}
#ifdef DIAGNOSTIC
	else if (p1 != &proc0)
		panic("cpu_fork: curproc");
#endif
	*pcb = p1->p_addr->u_pcb;

	/*
	 * Preset these so that gdt_compact() doesn't get confused if called
	 * during the allocations below.
	 *
	 * Note: pcb_ldt_sel is handled in the pmap_activate() call when
	 * we run the new process.
	 */
	p2->p_md.md_tss_sel = GSEL(GNULL_SEL, SEL_KPL);

	/*
	 * Activate the addres space.  Note this will refresh pcb_ldt_sel.
	 */
	pmap_activate(p2);

	/* Fix up the TSS. */
	pcb->pcb_tss.tss_rsp0 = (u_int64_t)p2->p_addr + USPACE - 16;
	pcb->pcb_tss.tss_ist[0] = (u_int64_t)p2->p_addr + PAGE_SIZE - 16;
	p2->p_md.md_tss_sel = tss_alloc(pcb);

	/*
	 * Copy the trapframe.
	 */
	p2->p_md.md_regs = tf = (struct trapframe *)pcb->pcb_tss.tss_rsp0 - 1;
	*tf = *p1->p_md.md_regs;

	setredzone(p2);

	/*
	 * If specified, give the child a different stack.
	 */
	if (stack != NULL)
		tf->tf_rsp = (u_int64_t)stack + stacksize;

	sf = (struct switchframe *)tf - 1;
	sf->sf_ppl = IPL_NONE;
	sf->sf_r12 = (u_int64_t)func;
	sf->sf_r13 = (u_int64_t)arg;
	if (func == child_return)
		sf->sf_rip = (u_int64_t)child_trampoline;
	else
		sf->sf_rip = (u_int64_t)proc_trampoline;
	pcb->pcb_rsp = (u_int64_t)sf;
	pcb->pcb_rbp = 0;
}