Make fork work, at least for kthreads. Switching still has some issues.
This commit is contained in:
parent
183439a14a
commit
4eed0cf1be
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=91467
@ -939,24 +939,6 @@ s_trap:
|
||||
FRAME_LEAVE(tempsave)
|
||||
rfi
|
||||
|
||||
/*
|
||||
* Child comes here at the end of a fork.
|
||||
* Mostly similar to the above.
|
||||
*/
|
||||
.globl fork_trampoline
|
||||
fork_trampoline:
|
||||
xor 3,3,3
|
||||
#if 0 /* XXX */
|
||||
bl lcsplx
|
||||
#endif
|
||||
mtlr 31
|
||||
mr 3,30
|
||||
blrl /* jump indirect to r31 */
|
||||
mr 3,30
|
||||
bl ast
|
||||
FRAME_LEAVE(tempsave)
|
||||
rfi
|
||||
|
||||
/*
|
||||
* DSI second stage fault handler
|
||||
*/
|
||||
|
@ -121,3 +121,14 @@ ENTRY(savectx)
|
||||
mfcr %r4 /* Save the condition register */
|
||||
stw %r4,PCB_CONTEXT(%r3)
|
||||
blr
|
||||
|
||||
/*
|
||||
* fork_trampoline()
|
||||
* Set up the return from cpu_fork()
|
||||
*/
|
||||
ENTRY(fork_trampoline)
|
||||
lwz %r3,CF_FUNC(1)
|
||||
lwz %r4,CF_ARG0(1)
|
||||
lwz %r5,CF_ARG1(1)
|
||||
bl fork_exit
|
||||
rfi
|
||||
|
@ -128,7 +128,7 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
|
||||
struct switchframe *sf;
|
||||
struct pcb *pcb;
|
||||
|
||||
KASSERT(td1 == curthread || td1 == thread0,
|
||||
KASSERT(td1 == curthread || td1 == &thread0,
|
||||
("cpu_fork: p1 not curproc and not proc0"));
|
||||
CTR3(KTR_PROC, "cpu_fork: called td1=%08x p2=%08x flags=%x", (u_int)td1, (u_int)p2, flags);
|
||||
|
||||
@ -137,8 +137,8 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
|
||||
|
||||
p1 = td1->td_proc;
|
||||
|
||||
pcb = (struct pcb *)(td2->td_kstack + KSTACK_PAGES * PAGE_SIZE -
|
||||
sizeof(struct pcb));
|
||||
pcb = (struct pcb *)((td2->td_kstack + KSTACK_PAGES * PAGE_SIZE -
|
||||
sizeof(struct pcb)) & ~0x2fU);
|
||||
td2->td_pcb = pcb;
|
||||
|
||||
/* Copy the pcb */
|
||||
@ -149,7 +149,6 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
|
||||
* Copy the trap frame for the return to user mode as if from a
|
||||
* syscall. This copies most of the user mode register values.
|
||||
*/
|
||||
|
||||
tf = (struct trapframe *)pcb - 1;
|
||||
bcopy(td1->td_frame, tf, sizeof(*tf));
|
||||
|
||||
@ -157,18 +156,13 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
|
||||
|
||||
td2->td_frame = tf;
|
||||
|
||||
/*
|
||||
* There happens to be a callframe, too.
|
||||
*/
|
||||
cf = (struct callframe *)tf - 1;
|
||||
cf->lr = (int)fork_trampoline;
|
||||
cf->cf_func = (register_t)fork_return;
|
||||
cf->cf_arg0 = (register_t)td2;
|
||||
cf->cf_arg1 = (register_t)tf;
|
||||
|
||||
/*
|
||||
* Below that, we allocate the switch frame.
|
||||
*/
|
||||
sf = (struct switchframe *)cf - 1;
|
||||
sf->sp = (int)cf;
|
||||
pcb->pcb_sp = (int)sf;
|
||||
pcb->pcb_sp = (register_t)cf;
|
||||
pcb->pcb_lr = (register_t)fork_trampoline;
|
||||
|
||||
/*
|
||||
* Now cpu_switch() can schedule the new process.
|
||||
@ -187,17 +181,15 @@ cpu_set_fork_handler(td, func, arg)
|
||||
void (*func) __P((void *));
|
||||
void *arg;
|
||||
{
|
||||
struct switchframe *sf;
|
||||
struct callframe *cf;
|
||||
|
||||
CTR3(KTR_PROC, "cpu_set_fork_handler: called with td=%08x func=%08x arg=%08x",
|
||||
(u_int)td, (u_int)func, (u_int)arg);
|
||||
|
||||
sf = (struct switchframe *)td->td_pcb->pcb_sp;
|
||||
cf = (struct callframe *)sf->sp;
|
||||
cf = (struct callframe *)td->td_pcb->pcb_sp;
|
||||
|
||||
cf->r31 = (register_t)func;
|
||||
cf->r30 = (register_t)arg;
|
||||
cf->cf_func = (register_t)func;
|
||||
cf->cf_arg0 = (register_t)arg;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -67,9 +67,9 @@ struct trapframe {
|
||||
|
||||
struct switchframe {
|
||||
register_t sp;
|
||||
int fill;
|
||||
int user_sr;
|
||||
int cr;
|
||||
register_t fill;
|
||||
register_t user_sr;
|
||||
register_t cr;
|
||||
register_t fixreg2;
|
||||
register_t fixreg[19]; /* R13-R31 */
|
||||
};
|
||||
@ -85,10 +85,9 @@ struct clockframe {
|
||||
* Call frame for PowerPC used during fork.
|
||||
*/
|
||||
struct callframe {
|
||||
register_t sp;
|
||||
register_t lr;
|
||||
register_t r30;
|
||||
register_t r31;
|
||||
register_t cf_func;
|
||||
register_t cf_arg0;
|
||||
register_t cf_arg1;
|
||||
};
|
||||
|
||||
#endif /* _MACHINE_FRAME_H_ */
|
||||
|
@ -38,18 +38,19 @@
|
||||
typedef int faultbuf[23];
|
||||
|
||||
struct pcb {
|
||||
u_int32_t pcb_context[18]; /* non-volatile r14-r31 */
|
||||
u_int32_t pcb_cr; /* Condition register */
|
||||
struct pmap *pcb_pm; /* pmap of our vmspace */
|
||||
struct pmap *pcb_pmreal; /* real address of above */
|
||||
register_t pcb_sp; /* saved SP */
|
||||
int pcb_spl; /* saved SPL */
|
||||
faultbuf *pcb_onfault; /* For use during copyin/copyout */
|
||||
int pcb_flags;
|
||||
register_t pcb_context[18]; /* non-volatile r14-r31 */
|
||||
register_t pcb_cr; /* Condition register */
|
||||
register_t pcb_sp; /* stack pointer */
|
||||
register_t pcb_lr; /* link register */
|
||||
struct pmap *pcb_pm; /* pmap of our vmspace */
|
||||
struct pmap *pcb_pmreal; /* real address of above */
|
||||
faultbuf *pcb_onfault; /* For use during
|
||||
copyin/copyout */
|
||||
int pcb_flags;
|
||||
#define PCB_FPU 1 /* Process had FPU initialized */
|
||||
struct fpu {
|
||||
double fpr[32];
|
||||
double fpscr; /* FPSCR stored as double for easier access */
|
||||
double fpr[32];
|
||||
double fpscr; /* FPSCR stored as double for easier access */
|
||||
} pcb_fpu; /* Floating point processor */
|
||||
};
|
||||
|
||||
|
@ -86,11 +86,15 @@ ASSYM(FRAME_EXC, offsetof(struct trapframe, exc));
|
||||
|
||||
ASSYM(SFRAMELEN, roundup(sizeof(struct switchframe), 16));
|
||||
|
||||
ASSYM(CF_FUNC, offsetof(struct callframe, cf_func));
|
||||
ASSYM(CF_ARG0, offsetof(struct callframe, cf_arg0));
|
||||
ASSYM(CF_ARG1, offsetof(struct callframe, cf_arg1));
|
||||
|
||||
ASSYM(PCB_CONTEXT, offsetof(struct pcb, pcb_context));
|
||||
ASSYM(PCB_CR, offsetof(struct pcb, pcb_cr));
|
||||
ASSYM(PCB_PMR, offsetof(struct pcb, pcb_pmreal));
|
||||
ASSYM(PCB_SP, offsetof(struct pcb, pcb_sp));
|
||||
ASSYM(PCB_SPL, offsetof(struct pcb, pcb_spl));
|
||||
ASSYM(PCB_LR, offsetof(struct pcb, pcb_lr));
|
||||
ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault));
|
||||
ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags));
|
||||
|
||||
|
@ -939,24 +939,6 @@ s_trap:
|
||||
FRAME_LEAVE(tempsave)
|
||||
rfi
|
||||
|
||||
/*
|
||||
* Child comes here at the end of a fork.
|
||||
* Mostly similar to the above.
|
||||
*/
|
||||
.globl fork_trampoline
|
||||
fork_trampoline:
|
||||
xor 3,3,3
|
||||
#if 0 /* XXX */
|
||||
bl lcsplx
|
||||
#endif
|
||||
mtlr 31
|
||||
mr 3,30
|
||||
blrl /* jump indirect to r31 */
|
||||
mr 3,30
|
||||
bl ast
|
||||
FRAME_LEAVE(tempsave)
|
||||
rfi
|
||||
|
||||
/*
|
||||
* DSI second stage fault handler
|
||||
*/
|
||||
|
@ -939,24 +939,6 @@ s_trap:
|
||||
FRAME_LEAVE(tempsave)
|
||||
rfi
|
||||
|
||||
/*
|
||||
* Child comes here at the end of a fork.
|
||||
* Mostly similar to the above.
|
||||
*/
|
||||
.globl fork_trampoline
|
||||
fork_trampoline:
|
||||
xor 3,3,3
|
||||
#if 0 /* XXX */
|
||||
bl lcsplx
|
||||
#endif
|
||||
mtlr 31
|
||||
mr 3,30
|
||||
blrl /* jump indirect to r31 */
|
||||
mr 3,30
|
||||
bl ast
|
||||
FRAME_LEAVE(tempsave)
|
||||
rfi
|
||||
|
||||
/*
|
||||
* DSI second stage fault handler
|
||||
*/
|
||||
|
@ -121,3 +121,14 @@ ENTRY(savectx)
|
||||
mfcr %r4 /* Save the condition register */
|
||||
stw %r4,PCB_CONTEXT(%r3)
|
||||
blr
|
||||
|
||||
/*
|
||||
* fork_trampoline()
|
||||
* Set up the return from cpu_fork()
|
||||
*/
|
||||
ENTRY(fork_trampoline)
|
||||
lwz %r3,CF_FUNC(1)
|
||||
lwz %r4,CF_ARG0(1)
|
||||
lwz %r5,CF_ARG1(1)
|
||||
bl fork_exit
|
||||
rfi
|
||||
|
@ -121,3 +121,14 @@ ENTRY(savectx)
|
||||
mfcr %r4 /* Save the condition register */
|
||||
stw %r4,PCB_CONTEXT(%r3)
|
||||
blr
|
||||
|
||||
/*
|
||||
* fork_trampoline()
|
||||
* Set up the return from cpu_fork()
|
||||
*/
|
||||
ENTRY(fork_trampoline)
|
||||
lwz %r3,CF_FUNC(1)
|
||||
lwz %r4,CF_ARG0(1)
|
||||
lwz %r5,CF_ARG1(1)
|
||||
bl fork_exit
|
||||
rfi
|
||||
|
@ -128,7 +128,7 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
|
||||
struct switchframe *sf;
|
||||
struct pcb *pcb;
|
||||
|
||||
KASSERT(td1 == curthread || td1 == thread0,
|
||||
KASSERT(td1 == curthread || td1 == &thread0,
|
||||
("cpu_fork: p1 not curproc and not proc0"));
|
||||
CTR3(KTR_PROC, "cpu_fork: called td1=%08x p2=%08x flags=%x", (u_int)td1, (u_int)p2, flags);
|
||||
|
||||
@ -137,8 +137,8 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
|
||||
|
||||
p1 = td1->td_proc;
|
||||
|
||||
pcb = (struct pcb *)(td2->td_kstack + KSTACK_PAGES * PAGE_SIZE -
|
||||
sizeof(struct pcb));
|
||||
pcb = (struct pcb *)((td2->td_kstack + KSTACK_PAGES * PAGE_SIZE -
|
||||
sizeof(struct pcb)) & ~0x2fU);
|
||||
td2->td_pcb = pcb;
|
||||
|
||||
/* Copy the pcb */
|
||||
@ -149,7 +149,6 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
|
||||
* Copy the trap frame for the return to user mode as if from a
|
||||
* syscall. This copies most of the user mode register values.
|
||||
*/
|
||||
|
||||
tf = (struct trapframe *)pcb - 1;
|
||||
bcopy(td1->td_frame, tf, sizeof(*tf));
|
||||
|
||||
@ -157,18 +156,13 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
|
||||
|
||||
td2->td_frame = tf;
|
||||
|
||||
/*
|
||||
* There happens to be a callframe, too.
|
||||
*/
|
||||
cf = (struct callframe *)tf - 1;
|
||||
cf->lr = (int)fork_trampoline;
|
||||
cf->cf_func = (register_t)fork_return;
|
||||
cf->cf_arg0 = (register_t)td2;
|
||||
cf->cf_arg1 = (register_t)tf;
|
||||
|
||||
/*
|
||||
* Below that, we allocate the switch frame.
|
||||
*/
|
||||
sf = (struct switchframe *)cf - 1;
|
||||
sf->sp = (int)cf;
|
||||
pcb->pcb_sp = (int)sf;
|
||||
pcb->pcb_sp = (register_t)cf;
|
||||
pcb->pcb_lr = (register_t)fork_trampoline;
|
||||
|
||||
/*
|
||||
* Now cpu_switch() can schedule the new process.
|
||||
@ -187,17 +181,15 @@ cpu_set_fork_handler(td, func, arg)
|
||||
void (*func) __P((void *));
|
||||
void *arg;
|
||||
{
|
||||
struct switchframe *sf;
|
||||
struct callframe *cf;
|
||||
|
||||
CTR3(KTR_PROC, "cpu_set_fork_handler: called with td=%08x func=%08x arg=%08x",
|
||||
(u_int)td, (u_int)func, (u_int)arg);
|
||||
|
||||
sf = (struct switchframe *)td->td_pcb->pcb_sp;
|
||||
cf = (struct callframe *)sf->sp;
|
||||
cf = (struct callframe *)td->td_pcb->pcb_sp;
|
||||
|
||||
cf->r31 = (register_t)func;
|
||||
cf->r30 = (register_t)arg;
|
||||
cf->cf_func = (register_t)func;
|
||||
cf->cf_arg0 = (register_t)arg;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user