Ejemplo n.º 1
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.
 */
void
cpu_fork(struct proc *p1, struct proc *p2, void *stack, void *tcb,
    void (*func)(void *), void *arg)
{
	struct cpu_info *ci = curcpu();
	struct pcb *pcb = &p2->p_addr->u_pcb;
	struct pcb *pcb1 = &p1->p_addr->u_pcb;
	struct trapframe *tf;
	struct switchframe *sf;

	/* Save the fpu h/w state to p1's pcb so that we can copy it. */
	if (p1 != &proc0 && (ci->ci_flags & CPUF_USERXSTATE))
		fpusave(&pcb1->pcb_savefpu);

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

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

	/*
	 * 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 -
	    (arc4random() & PAGE_MASK & ~_STACKALIGNBYTES);

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

	setguardpage(p2);

	/*
	 * If specified, give the child a different stack and/or TCB
	 */
	if (stack != NULL)
		tf->tf_rsp = (u_int64_t)stack;
	if (tcb != NULL)
		pcb->pcb_fsbase = (u_int64_t)tcb;

	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;
}
Ejemplo n.º 2
0
static void
save_guest_fpustate(struct vcpu *vcpu)
{

	if ((rcr0() & CR0_TS) == 0)
		panic("fpu emulation not enabled in host!");

	/* save guest XCR0 and restore host XCR0 */
	if (rcr4() & CR4_XSAVE) {
		vcpu->guest_xcr0 = rxcr(0);
		load_xcr(0, vmm_get_host_xcr0());
	}

	/* save guest FPU state */
	fpu_stop_emulating();
	fpusave(vcpu->guestfpu);
	fpu_start_emulating();
}