* Initialise pcb_pmap for new threads.
* Add support for forking new threads from &thread0 as well as curthread.
This commit is contained in:
parent
92e814dcb6
commit
34da0be411
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=92286
@ -134,6 +134,9 @@ cpu_fork(td1, p2, td2, flags)
|
||||
struct trapframe *p2tf;
|
||||
u_int64_t bspstore, *p1bs, *p2bs, rnatloc, rnat;
|
||||
|
||||
KASSERT(td1 == curthread || td1 == &thread0,
|
||||
("cpu_fork: p1 not curproc and not proc0"));
|
||||
|
||||
if ((flags & RFPROC) == 0)
|
||||
return;
|
||||
|
||||
@ -174,9 +177,8 @@ cpu_fork(td1, p2, td2, flags)
|
||||
* is started, to resume here, returning nonzero from setjmp.
|
||||
*/
|
||||
#ifdef DIAGNOSTIC
|
||||
if (td1 != curthread)
|
||||
panic("cpu_fork: curproc");
|
||||
ia64_fpstate_check(td1);
|
||||
if (td1 == curthread)
|
||||
ia64_fpstate_check(td1);
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -184,10 +186,13 @@ cpu_fork(td1, p2, td2, flags)
|
||||
*
|
||||
* 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.
|
||||
* will be to right address, with correct registers. Clear the
|
||||
* high-fp enable for the new process so that it is forced to
|
||||
* load its state from the pcb.
|
||||
*/
|
||||
td2->td_frame = (struct trapframe *)td2->td_pcb - 1;
|
||||
bcopy(td1->td_frame, td2->td_frame, sizeof(struct trapframe));
|
||||
td2->td_frame->tf_cr_ipsr |= IA64_PSR_DFH;
|
||||
|
||||
/*
|
||||
* Set up return-value registers as fork() libc stub expects.
|
||||
@ -205,15 +210,21 @@ cpu_fork(td1, p2, td2, flags)
|
||||
*
|
||||
* We could cope with td1!=curthread by digging values
|
||||
* out of its PCB but I don't see the point since
|
||||
* current usage never allows it.
|
||||
* current usage only allows &thread0 when creating kernel
|
||||
* threads and &thread0 doesn't have any dirty regs.
|
||||
*/
|
||||
__asm __volatile("mov ar.rsc=0;;");
|
||||
__asm __volatile("flushrs;;" ::: "memory");
|
||||
__asm __volatile("mov %0=ar.bspstore" : "=r"(bspstore));
|
||||
|
||||
p1bs = (u_int64_t *)td1->td_kstack;
|
||||
p2bs = (u_int64_t *)td2->td_kstack;
|
||||
|
||||
if (td1 == curthread) {
|
||||
__asm __volatile("mov ar.rsc=0;;");
|
||||
__asm __volatile("flushrs;;" ::: "memory");
|
||||
__asm __volatile("mov %0=ar.bspstore" : "=r"(bspstore));
|
||||
} else {
|
||||
bspstore = (u_int64_t) p1bs;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy enough of td1's backing store to include all
|
||||
* the user's stacked regs.
|
||||
@ -225,29 +236,37 @@ cpu_fork(td1, p2, td2, flags)
|
||||
* where the last ar.rnat which covers the user's
|
||||
* saved registers would be placed. If so, we read
|
||||
* that one from memory, otherwise we take td1's
|
||||
* current ar.rnat.
|
||||
* current ar.rnat. If we are simply spawning a new kthread
|
||||
* from &thread0 we don't care about ar.rnat.
|
||||
*/
|
||||
rnatloc = (u_int64_t)p1bs + td1->td_frame->tf_ndirty;
|
||||
rnatloc |= 0x1f8;
|
||||
if (bspstore > rnatloc)
|
||||
rnat = *(u_int64_t *) rnatloc;
|
||||
else
|
||||
__asm __volatile("mov %0=ar.rnat;;" : "=r"(rnat));
|
||||
|
||||
/*
|
||||
* Switch the RSE back on.
|
||||
*/
|
||||
__asm __volatile("mov ar.rsc=3;;");
|
||||
if (td1 == curthread) {
|
||||
rnatloc = (u_int64_t)p1bs + td1->td_frame->tf_ndirty;
|
||||
rnatloc |= 0x1f8;
|
||||
if (bspstore > rnatloc)
|
||||
rnat = *(u_int64_t *) rnatloc;
|
||||
else
|
||||
__asm __volatile("mov %0=ar.rnat;;" : "=r"(rnat));
|
||||
|
||||
/*
|
||||
* Switch the RSE back on.
|
||||
*/
|
||||
__asm __volatile("mov ar.rsc=3;;");
|
||||
} else {
|
||||
rnat = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup the child's pcb so that its ar.bspstore
|
||||
* starts just above the region which we copied. This
|
||||
* should work since the child will normally return
|
||||
* straight into exception_restore.
|
||||
* straight into exception_restore. Also initialise its
|
||||
* pmap to the containing proc's vmspace.
|
||||
*/
|
||||
td2->td_pcb->pcb_bspstore = (u_int64_t)p2bs + td1->td_frame->tf_ndirty;
|
||||
td2->td_pcb->pcb_rnat = rnat;
|
||||
td2->td_pcb->pcb_pfs = 0;
|
||||
td2->td_pcb->pcb_pmap = (u_int64_t)
|
||||
vmspace_pmap(td2->td_proc->p_vmspace);
|
||||
|
||||
/*
|
||||
* Arrange for continuation at fork_return(), which
|
||||
|
Loading…
Reference in New Issue
Block a user